线程池工厂方法源码分析

里面都是静态方法,为Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, and Callable classes提供工厂方法

 

创建一个线程池,该线程池重用在共享的无边界队列上运行的固定数量的线程。 在任何时候,最多nThreads个线程是活动的,用于处理任务。如果在所有线程都处于活动状态时提交了其他任务,则它们将在队列中等待直到一个线程可用。如果任何线程由于执行过程中的异常导致在shutdown之前终止,如果需要执行后续的task,则将会新建一个线程替换原来异常的线程。池中的线程将一直存在,直到显式地调用shutdown为止。

 

创建一个Executor,使用在不受限制的队列上操作的单个工作线程。 

(但是请注意,如果该单线程在terminate之前由于执行过程中的失败而终止,则在需要执行新任务时将使用新线程代替。)

能够保证任务按提交顺序执行,并且在任何给定时间活动的任务不超过一个。 

newFixedThreadPool(1)不同,保证返回的executor不可重新配置成使用其他线程。

如下例

ExecutorService fixed = Executors.newFixedThreadPool(1);

ExecutorService single = Executors.newSingleThreadExecutor();

        ThreadPoolExecutor executor = (ThreadPoolExecutor) single;

        executor.setMaximumPoolSize(4);

上面代码会报错。

Exception in thread "main" java.lang.ClassCastException: class java.util.concurrent.Executors$FinalizableDelegatedExecutorService cannot be cast to class java.util.concurrent.ThreadPoolExecutor (java.util.concurrent.Executors$FinalizableDelegatedExecutorService and java.util.concurrent.ThreadPoolExecutor are in module java.base of loader 'bootstrap')

at test/test.test.main(test.java:9)

第九行代码是ThreadPoolExecutor executor = (ThreadPoolExecutor) single;

发生了类型转换失败的错误

改成

ThreadPoolExecutor executor = (ThreadPoolExecutor) fixed;

则不会报错

具体原理见后面一节的源码分析。

对于耗时短、大量的异步任务性能更好

使用execute会重新调用前面构建的线程

一个线程60s没用后就会被terminate,因此一个长时间闲置的线程池不会耗费任何资源

Idel 闲置的

还有好一些静态方法来构造线程池对象ExecutorService,需要时再看吧

下面常用的几个线程池工厂方法都是利用ThreadPoolExecutor对象来实现的

 

 

newFixedThreadPool指定固定线程池有n个线程,因此没有所谓的超时时间概念,指定为0即可。

工作队列为LinkedBlockingQueue,线性阻塞队列。

 

工作队列也为LinkedBlockingQueue,线性阻塞队列,由于只有一个工作线程,因此能保证按顺序执行。

跟newFixedThreadPool区别在于线程数固定为1,而且给生成的ThreadPoolExecutor传入给FinalizableDelegatedExecutorService对象,即newSingleThreadExecutor其实就是newFixedThreadPool(1)用FinalizableDelegatedExecutorService()包裹起来的产物。

FinalizableDelegatedExecutorService是Executors工厂类里面的一个静态私有类。

这个类内部除了构造方法之外只有一个GC时停掉线程池的方法,我们都知道Java中的内存管理一般都是JVM来完成的,程序员不需要做什么事情,所以这个方法我们可以不看。这个类继承了DelegatedExecutorService,我们来看看这个类的源码

由注释可知,这个类是一个包装类,只公开ExecutorService接口的ExecutorService方法,因此没有ThreadPoolExecutor中部分修改线程池的方法。

下面这段代码,首先single不是一个ThreadPoolExecutor类的对象,它只是一个ExecutorService对象,首先类型转换就报错了,也没有setMaximumPoolSize这些方法。

ExecutorService fixed = Executors.newFixedThreadPool(1);

ExecutorService single = Executors.newSingleThreadExecutor();

        ThreadPoolExecutor executor = (ThreadPoolExecutor) single;

        executor.setMaximumPoolSize(4);

 

可以看到平常的线程数目为0,最大线程数目为最大整数,超过60s时就会杀掉空闲线程。

工作队列为同步队列SynchronousQueue

ThreadPoolExecutor实现了ExecutorService接口

public class ThreadPoolExecutor extends AbstractExecutorService {

public abstract class AbstractExecutorService implements ExecutorService {

 

 

corePoolSize参数指定,平常状态下线程池中的线程数目(尽管线程是空闲的)

Idle空闲的

maximumPoolSize指定线程池中的最大线程数

keepAliveTime,当线程池中线程数目超过corePoolSize时(小于maximumPoolSize),则超过的那些空闲线程会等待keepAliveTime,超过keepAliveTime还没有新任务时则会terminate

TimeUnit,keepAliveTime参数的时间单位

workQueue指定用于暂存任务的队列,这个队列只能存储用execute方法提交的Runnable任务,但是ExecutorService支持提交Callable任务呀,查看AbstractExecutorService源码可见,重载的submit方法中,代码实现方式是,将Callable参数转换成一个RunnableFuture(也是一个Runnable对象,然后使用execute方法来执行任务,RunnableFuture还能作为结果来返回。因此,使用submit和传入Callable任务都能使用workQueue来暂存任务队列。

threadFactory线程工厂,线程的工厂类,用于生成一个线程。

handler 当由于达到线程限制数目或队列容量而阻塞执行时,使用handler处理。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值