java 线程池中的状态转换 - 使用位运算表示状态
java 线程池中的状态转换
需要表示2种类型的状态, 1种是线程池是否在运行中, 1种是线程池中的有效线程数目.
java源代码中, 并不使用2个变量来分别表示上面的状态, 而是使用1个整数来表示. 为此, 线程池限制了最大的线程数目为 (2^29)-1
而不是 (2^31)-1
. 这样做的目的是使代码更快, 更简单.
线程有以下的状态:
- RUNNING: 接受新的任务并处理队列中的任务
- SHUTDOWN: 不接受新的任务,但是继续处理队列中的任务
- STOP: 不接受新的任务,也不处理队列中的任务,并中断当前的任务
- TIDYING: 所有的任务都停止, workerCount 为 0 , 线程转换为 TIDYING 状态, 将会执行
terminated()
钩子方法 - TERMINATED:
terminated()
调用完成
为了比较状态, 数字顺序是有用的. runState 是单调递增的:
-
RUNNING
->SHUTDOWN
调用shutdown()
的时候触发, 可能隐式地在 finally 块中调用 - (
RUNNING
orSHUTDOWN
) ->STOP
调用shutdownNow()
的时候触发 -
SHUTDOWN
->TIDYING
当 任务队列 和 线程池 都为空的时候 -
STOP
->TIDYING
当 线程池为空的时候 -
TIDYING
->TERMINATED
当terminated()
钩子函数执行完成的时候
在 awaitTermination()
中等待的线程会在状态达到 TERMINATED 的时候返回
SHUTDOWN
到 TIDYING
的状态过渡并不直接, 因为 任务队列 可能 SHUTDOWN
状态中由 非空之后变成空, 也可能由空变成非空. 但是我们能在 看到任务队列为空后, workerCount 也为空的情况下才进入 terminate.
源码状态定义:
这里面的 COUNT_BITS
就是 Integer.SIZE(32) - 3 = 29, 减去最高位的符号位, 用Integer 的最高两位来标识当前线程池的状态.
整个表示示意图如上, 其中CAPACITY
就是 29 个1 , 当我们要拿当前线程池的状态的时候, 就用 c & ~CAPCITY
来清空后29位
private static int runStateOf(int c) { return c & ~CAPACITY; }
需要拿线程数量的时候, 就用 c & CAPACITY;
来截取后29位
private static int workerCountOf(int c) { return c & CAPACITY; }
而 ctlOf
函数表示合并 rs (running state)
和 wc (workerCount)
, 所以初始化的 ctl
为 clt(RUNNING,0)
, 表示运行状态 和 0 个 worker 数目. (这命名… 不算是好的实践吧)
private static int ctlOf(int rs, int wc) { rs | wc }
位运算的基础用法了.
本文地址:https://blog.csdn.net/sparrowxin/article/details/111875851