线程池构造详解
Java中的Class ThreadPoolExecutor
public class ThreadPoolExecutor extends AbstractExecutorService
该类是线程池的核心类,使用线程池时就是实例化该类的过程,这个类提供了4个构造方法:
//创建一个新的 ThreadPoolExecutor与给定的初始参数和默认线程工厂和拒绝执行处理程序。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue);
//创建一个新的 ThreadPoolExecutor与给定的初始参数和默认线程工厂。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler);
//创建一个新的 ThreadPoolExecutor与给定的初始参数和默认拒绝执行处理程序。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory);
//创建一个新 ThreadPoolExecutor给定的初始参数。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);
参数详解
构造方法中一共使用到了七个参数,含义分别为:
corePoolSize
- 即使空闲时仍保留在池中的线程数,除非设置allowCoreThreadTimeOut
maximumPoolSize
- 池中允许的最大线程数keepAliveTime
- 当线程数大于核心线程数时,这是多余的空闲线程在终止前等待新任务的最大时间。unit
-keepAliveTime
参数的时间单位workQueue
- 用于在执行任务之前使用的队列。 这个队列将仅保存execute
方法提交的Runnable
任务。threadFactory
- 执行程序创建新线程时使用的工厂handler
- 执行被阻止时使用的处理程序,因为达到线程限制和队列容量
线程池工作顺序
线程池的工作顺序为:
- 线程池创建,准备好
corePoolSize
数量的核心线程,准备接收任务 - 当core满了时,就将再进来的任务放入到阻塞队列中,空闲的core线程就去自动去阻塞队列获取任务执行
- 当阻塞队列满了时,就去直接开新进程执行,最大只能开到
maximumPoolSize
数量的线程 - 当开到最大线程数依然满足不了任务数时,就会调用RejectedExecutionHandler拒绝任务
- 如果当前线程池具有多于
corePoolSize
线程,则如果空闲超过keepAliveTime
,则多余的线程将被终止max线程都执行完成
拒绝策略
当执行程序对最大线程和工作队列容量使用有限边界并且饱和时,会触发拒绝策略,RejectedExecutionHandler提供了四个预定义的处理程序策略:
-
默认ThreadPoolExecutor.AbortPolicy ,丢弃任务并抛出异常。
-
在ThreadPoolExecutor.CallerRunsPolicy中,由调用execute本身的线程运行任务, 这提供了一个简单的反馈控制机制,将降低新任务提交的速度。
-
在ThreadPoolExecutor.DiscardPolicy中 ,简单地删除无法执行的任务,但不抛出异常。
-
在ThreadPoolExecutor.DiscardOldestPolicy中 ,如果执行程序没有关闭,则工作队列头部的任务被删除,然后重试执行(可能会再次失败,导致重复)。
为什么要使用线程池
减低资源消耗
通过重复利用已经创建好的线程降低线程创建和销毁带来的损耗
提高相应速度
当线程池中有等待分配任务的线程时,新任务来临时无需创建新线程即可执行
提高线程的可管理性
线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。无限的创建和销毁线程不仅消耗系统资源,还减低系统的稳定性,使用线程池可进行统一分配。