线程池状态
ThreadPoolExcutor使用int高3位来表示线程池状态,低29位表示线程数量
状态 | 高三位 | 接收新任务 | 处理阻塞队列任务 | 说明 |
RUNNING | 111 | Y | Y | |
SHUTDOWN | 000 | N | Y | 不会接收新任务,但会处理阻塞队列剩余任务,比较温和,已经提交的任务都会执行。 |
STOP | 001 | N | N | 会中断正在执行的任务,并抛弃阻塞队列任务,比较暴力。 |
TIDYING | 010 | 任务全部执行完毕,活动线程为0即将进入终结 | ||
TERMINATED | 011 | 终结状态 |
从数字上比较:
TERMINATED > TIDYING > STOP > SHUTDOWN > RUNNING
RUNNING 111, 最高位1表示负数。
问题
为啥将线程池的状态和线程数量存在一个int类型的变量中?
存储在一个原子变量ctl中,目的是将线程池状态与线程个数合二为一,这样就可以用一次cas原子操作进行赋值。
构造方法
corePoolSize 核心线程数目(最多保留的线程数)
maxmumPoolSize 最大线程数目
keepAliveTime 生存时间-针对救急线程
unit 时间单位-针对救急线程
workQueue 阻塞队列
threadFactory 线程工厂-可以为线程创建时起好名字
handler 拒绝策略
最大线程数 = 核心线程数 + 救急线程数
执行流程:先给核心线程执行任务,然后再将线程放到阻塞队列中,最后给救急线程执行任务,最后执行拒绝策略。
最开始线程池里是没有线程的,属于一种懒加载,只有有任务要执行的时候,才会创建线程。
救急线程与核心线程的区别:
救急线程是有存活时间的。
核心线程执行完任务会一直保留在线程池中。
拒绝策略:
AbortPolicy 让调用者抛出RejectedExecutionException异常,默认策略。
CallerRunsPolicy 让调用者运行任务。
DiscardPolicy 放弃本次任务。
DiscardOldestPolicy 放弃队列中最早的任务,本任务取而代之。
这是jdk提供的这四种拒绝策略都实现了RejectedExecutionHandler接口:
还有第三方框架提供的实现:
1.Dubbo实现,抛出RejectedExecutionException异常之前会记录日志,并dump线程栈信息,方便定位问题。
2.Netty实现,创建一个新线程来执行任务。
3.ActiveMQ的实现,带超时等待60s尝试放入队列,类似之前自定义拒绝策略。
4.PinPoint的实现,使用了一个拒绝策略链,会逐一尝试策略链中没中拒绝策略。