threadpoolexecutor用int型ctl变量高3位存运行状态、低29位存工作线程数,通过位运算分离合并;running状态为111₂(−536870912),workercount最大值为536870911。

ThreadPoolExecutor 用一个 int 类型的原子变量 ctl 同时保存线程池的运行状态(runState)和工作线程数量(workerCount),靠的是**位运算分离与合并**——高 3 位存状态,低 29 位存线程数。
ctl 的位布局设计
Java 中 int 是 32 位有符号整数。ThreadPoolExecutor 定义:
- 高 3 位(第 31、30、29 位,从 0 开始计)表示 runState(如 RUNNING=111₂=−536870912)
- 低 29 位(第 0~28 位)表示 workerCount(最大值为 2²⁹−1 = 536,870,911)
- 两者通过按位或(|)组合:`ctl = (runState
如何从中提取状态和线程数
利用掩码(mask)配合位运算快速拆分:
- 取运行状态:`runState = ctl & ~CAPACITY`,其中 `CAPACITY = (1
- 取线程数:`workerCount = ctl & CAPACITY`,只保留低 29 位
为什么这样设计
核心是为了保证 状态 + 数量的更新具有原子性:
- 避免分别用两个 volatile 变量(runState 和 workerCount)导致竞态:比如 CAS 修改 workerCount 时,runState 可能已被其他线程改变,造成不一致
- 单变量 CAS(如 `compareAndSet(ctl, expect, update)`)一次操作即可安全更新二者,符合“读-改-写”原子需求
- 29 位足够支持超大线程数(5 亿+),远超实际场景需要;3 位刚好编码 5 种状态(RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED)
典型操作示例
比如调用 `execute()` 前要检查是否 RUNNING 并尝试增加线程数:
- 先 `rs = runStateOf(ctl.get())` 判断状态
- 若为 RUNNING,则循环尝试 CAS:`compareAndSet(ctl, c, c + 1)`(c+1 即 workerCount 加 1,状态位不变)
- 失败说明有竞争,重新读 ctl 再试——整个过程基于单变量原子操作,状态与数量始终同步
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











