java并发程序设计总结六:线程池

多线程的软件设计方法确实可以最大限度的发挥现代多核处理器的计算能力,但是如果不加控制和管理的随意使用创建线程,对系统的性能反而会产生不利的影响。

不适用线程池的线程优化

可以使用如下方式来创建线程,他会在run结束之后,自动回收线程资源:
在线程比较少的情况下使用这种方式到是没有什么问题,但是在真实环境中,通常需要创建很多的线程,而这样反而会耗尽CPU和内存资源

线程池的概念

使用过数据库开发的话,我们应该都知道数据库连接池,为了避免每次数据库查询都重新建立和销毁数据库连接,我们可以在数据库连接池中维护一些数据库连接connection并让他们长期保持在激活状态。这样一来,每当系统需要使用数据库时,并不是创建一个新的连接,而是直接从连接池中取出一个连接对象;而每当用完的时候,不是去关闭连接,而是将它还给数据库连接池。通过这种方式,可以节省不少的创建和销毁对象的时间。线程池和数据库连接池的原理是一样的

JDK对线程池的支持

为了能够更好的控制多线程,JDK提供了一套Executor框架,存在于java.util.concurrent包中,是jdk并发包的核心类。其中,ThreadPoolExecutor/ExecutorService/ScheduleExecutorService都可以表示一个线程池,存放线程对象;Executors类则扮演者线程池工厂的角色,通过Executors的一系列方法可以取得特定功能的线程池。,主要方法如下:

线程池的简单使用

在最后我们使用了shutdown关闭了线程池,如果省略这行代码,会发现程序将一直处于运行状态,因为线程池中的线程会一直处于激活状态

计划任务:ScheduledExecutorService线程池

ScheduledExecutorService线程池扩展了ExecutorService线程池,它可以根据时间需要对线程进行调度。它的主要方法签名如下:
下面通过一个实例code来解析这三个方法(主要是分辨后面两个方法的区别)

核心线程池的内部实现

前面所说的几个创建线程池的方法,其实无论是newFixedThreadPool还是newSingleThreadExecutor还是newCachedThreadPool,他们的内部实现都是通过ThreadPoolExecutor构造器,其方法声明如下:
对于ThreadPoolExecutor类来说,他有很多的重载构造器,如下是它的包含所有的参数的构造器:
对于ThreadPoolExecutor线程池的构造器,其中的workQueue和handler需要进行详细的说明

拒绝策略

以上内置的四种策略都实现了RejectedExecutionHandler接口,我们也可以通过实现该接口来实现自己的拒绝策略。该接口的定义如下:

线程工厂ThreadFactory

线程工厂主要是用于创建线程池中的线程对象,ThreadFactory是一个接口,它只有一个方法,用来创建线程,当线程池需要新建线程时,就会调用这个方法:
我们也可以通过实现ThreadFactory接口来实现自定义创建线程对象

扩展线程池

ThreadPoolExecutor是一个可扩展的线程池,它提供了三个方法用于对线程池进行控制

线程池异常隐藏

在这里需要注意的是,当我们调用线程池的submit方法来提交任务时,如果当前任务有错误,最终执行的结果中是看不到错误的,只会让该结果不显示出来,可以说线程池将错误吃了。对于这种情况,我们可以使用两种办法解决:1.使用execute代替submit提交任务;2.简单修改一下submit方式提交:
通过上面两种方法之一修改提交,最终输出的结果会打印出错误时的堆栈异常信息

来源:19年,重新开始写

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2017年9月20日
下一篇 2017年9月20日

相关推荐