线程池的状态及其处理的技巧
线程池的状态及其处理的技巧
线程的状态
线程池有5种状态:
-
Running,:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理
-
SHUTDOWN,:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务
-
STOP,:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务
-
TIDYING:当所有的任务已终止,ctl记录的"任务数量"为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。
- 例如:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING
-
TERMINATED:线程池彻底终止,就变成TERMINATED状态
线程池的状态量
1 private static final int RUNNING = -1 << COUNT_BITS; -- 对应的高3位值是111。
2 private static final int SHUTDOWN = 0 << COUNT_BITS; -- 对应的高3位值是000。
3 private static final int STOP = 1 << COUNT_BITS; -- 对应的高3位值是001。
4 private static final int TIDYING = 2 << COUNT_BITS; -- 对应的高3位值是010。
5 private static final int TERMINATED = 3 << COUNT_BITS; -- 对应的高3位值是011。
线程池使用一个原子整型来控制线程池的状态:
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
-
ctl是原子整形,cas锁,操作具有原子、有序、可见性
-
ctl分为两个组成部分,一个是runState(线程池状态),一个是workerCount(工作线程数)
-
ctlof将两个状态进行打包:
private static int ctlOf(int rs, int wc) { return rs | wc; }
因为连个状态占据的是高3位和低29位所以不会冲突
状态获取
1 //拆包函数
2 private static int runStateOf(int c) { return c & ~CAPACITY; }
3 private static int workerCountOf(int c) { return c & CAPACITY; }
4 //打包函数
5 private static int ctlOf(int rs, int wc) { return rs | wc; }
主要通过COUNT_BITS和CAPACITY获取状态
1 private static final int COUNT_BITS = Integer.SIZE - 3;
2 private static final int CAPACITY = (1 << COUNT_BITS) - 1;