线程池中的线程执行完任务后进入等待状态而非销毁,由while循环和阻塞队列共同维持:核心线程调用take()无限阻塞,非核心线程poll()超时退出;异常未捕获或主动终止会导致线程异常退出。

线程池里的线程执行完任务后,并不会退出或销毁,而是进入等待状态,随时准备接下一个任务——这不是靠外部干预,而是由线程自身循环逻辑和阻塞队列共同维持的。
线程靠 while 循环持续“守着”任务队列
每个工作线程(Worker)启动后,会运行 runWorker 方法,里面是一个典型的循环结构:
while (task != null || (task = getTask()) != null)
只要能从队列里取到任务(哪怕当前为空、需阻塞等待),线程就继续执行;取不到且满足回收条件,才退出循环、终止线程。
阻塞队列是保活的关键载体
getTask() 方法内部根据线程类型决定用哪种方式取任务:
- 核心线程默认调用 workQueue.take():无任务时无限期阻塞,线程状态变为 WAITING,不消耗 CPU,但保持存活
- 非核心线程调用 workQueue.poll(keepAliveTime, unit):超时未取到任务就返回 null,循环结束,线程自然终止
- 若设置了 allowCoreThreadTimeOut(true),核心线程也走 poll 超时逻辑,同样可能被回收
线程存活不等于“一直占用资源”
处于 take() 或 timed poll() 等待中的线程,实际处于 JVM 的 WAITING 或 TIMED_WAITING 状态:
- 不占用 CPU 时间片
- 栈内存持续保留(约 1MB/线程),但这是复用的前提
- 操作系统线程句柄、JVM 线程对象仍存在,只是挂起
避免意外退出才能真正保活
线程中途抛出未捕获异常、或 run() 方法提前 return,都会导致循环中断,Worker 异常退出。因此:
- 任务逻辑中应妥善处理异常,防止传播到 runWorker 外层
- 不要在任务里调用 System.exit() 或直接 stop() 线程
- 注意 ThreadLocal 变量清理,否则可能引发内存泄漏,间接影响线程复用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











