worker继承aqs的核心目的是为单个线程执行加“状态锁”以防止运行中被中断,具体通过state字段实现:-1(构造后禁止中断)、0(空闲/解锁可中断)、1(任务完成待回收),且锁不可重入以避免死锁。

Worker 继承 AQS 不是为了控制并发任务调度,而是为了给单个线程执行过程加一道“状态锁”,确保任务运行期间不被意外中断——这是它最核心的设计意图。
Worker 用 AQS 做什么?就两件事:防中断 + 标状态
Worker 的 run() 方法最终会调用 runWorker(this),这个方法里包裹着一个 while 循环,不断取任务、执行。但任务执行中如果外部调用 interrupt(),线程可能被强行打断,导致业务逻辑异常或资源未释放。
Worker 利用 AQS 的 state 字段做运行状态标记:
- 构造时 setState(-1):禁止启动前被中断(比如线程还没跑起来就被 shutdown)
- runWorker 开始执行 firstTask 前调用 lock():把 state 设为 0,表示“正在干活”,此时再 interrupt 就不会生效
- 任务 run() 完成后调用 unlock():state 变回 0(解锁),允许后续中断操作进入 getTask() 阻塞阶段生效
注意:AQS 在这里不是用来排队抢锁的,也不支持重入——Worker 明确设计为不可重入锁,防止任务执行中调用 setCorePoolSize 等线程池控制方法时又试图获取同一把锁,造成死锁。
为什么不用 ReentrantLock?就因为要“不重入”
ReentrantLock 允许同一线程多次 lock/unlock,但 Worker 必须避免在执行任务时响应中断请求。如果用了可重入锁,当任务内部调用线程池管理方法(比如 shutdownNow),就可能触发 interruptIdleWorkers → tryLock → 成功 → 中断正在跑的任务,破坏原子性。
而 AQS 自定义实现的简单互斥锁天然不可重入,只要 state != 0,tryAcquire 就失败,从而把中断拦截在任务执行之外。
中断真正起效的地方:getTask() 的阻塞点
Worker 的生命周期由 getTask() 决定。当队列为空、且满足超时条件(比如非核心线程空闲超 keepAliveTime),getTask() 返回 null,while 循环退出,runWorker 结束,线程自然终止。
在这个“等待新任务”的阶段,Worker 是 unlocked 状态(state == 0),interrupt() 才能穿透进来,唤醒 take() 或 poll(),让 getTask() 提前返回 null,实现优雅退出。
换句话说:AQS 锁只管“干活时不被打断”,不管“等活时不能叫醒”——叫醒权交给阻塞队列和中断信号协同完成。
state 的三个典型值,对应 Worker 的三种生命态
Worker 的 AQS state 并非用于同步竞争,而是语义化标识:
- -1:刚构造完,线程尚未 start,禁止任何中断(初始化抑制)
- 0:空闲或已退出,可被中断;也可表示锁已释放
- 1:已执行过 unlock(),表示该 Worker 已完成使命(completedTasks 统计完毕,准备回收)
这种轻量级状态管理,比用 volatile boolean 更可靠,也比引入额外锁对象更紧凑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











