Executors常用线程池区分
Executors是jdk中的一个工具包,提供了几种线程池的构建;分析一下各个线程池的实现与使用场景避免用错。
汇总
newFixedThreadPool
1 | public static ExecutorService newFixedThreadPool(int nThreads) { |
关注这几个线程池的入参:
- 核心线程数与最大线程数相等;
- 线程超时时间为0;
- 任务队列是LinkedBlockingQueue;
根据参数就可以判断这个线程池的特性:
线程池中的线程最大可以达到nThreads,由于线程没有超时时间所以线程达到nThreads后这些线程会一直缓存着不会结束。任务队列是LinkedBlockingQueue,可以理解为任务加入没有上限(实际是最大整数)。注意LinkedBlockingQueue达到上限只是等待,而不是添加失败。
使用场景
newFixedThreadPool是比较通用的线程池,不过线程没有超时时间,所以要判断好线程数避免过多的线程空闲无用。
newCachedThreadPool
1 | public static ExecutorService newCachedThreadPool() { |
关注这几个线程池的入参:
- 核心线程数为0,最大线程数为最大整型;
- 线程超时时间为60秒;
- 任务队列是SynchronousQueue;
SynchronousQueue是堵塞队列得一种,其特性是put操作和take操作必须是互相唤醒的,比如:put操作,必须take操作唤醒,take操作必须put操作唤醒,没有take操作,多个put操作都堵塞,等待一个一个take操作来一个一个唤醒,同理,take操作也一样,跟他的名字一样,同步队列,就好像,你是救我的药,我也是救你的药
如果没有take在等待,直接执行offer会立即返回false,而线程池中使用的就是offer方法。
特性
可缓存的线程池,调用execute()方法将重用之前构造的线程(如果线程可用)。如果每有线程可用,则创建一个新线程并加入池中。终止并从缓存中移除那些超过60秒未使用的线程。由于SynchronousQueue的特性(offer方法),使得没有空闲线程时就会添加新线程。
场景
适合用于任务执行时间较短的情况。
newScheduledThreadPool
1 | public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { |
一个普通的延时/定时任务线程池。
newWorkStealingPool
1 | public static ExecutorService newWorkStealingPool() { |
newWorkStealingPool适合使用在很耗时的操作,但是newWorkStealingPool不是ThreadPoolExecutor的扩展,它是新的线程池类ForkJoinPool的扩展,但是都是在统一的一个Executors类中实现,由于能够合理的使用CPU进行对任务操作(并行操作),所以适合使用在很耗时的任务中。
newSingleThreadExecutor
1 | public static ExecutorService newSingleThreadExecutor() { |
一个只有一个线程的线程池。
FinalizableDelegatedExecutorService实现了finalize()方法,在finalize方法中执行shutdown()。