worker是threadpoolexecutor的内部类,封装thread并驱动其通过while循环持续从任务队列取任务执行:先运行firsttask,再反复调用gettask()阻塞获取新任务,直至返回null才退出,实现单线程复用执行多个任务。

Java 线程池通过 Worker 对象实现线程复用,核心不是“让线程不退出”,而是让每个 Worker 封装一个 Thread,并驱动它持续从任务队列中取任务执行——一次创建,多次使用。
Worker 是什么:封装线程 + 执行循环
Worker 是 ThreadPoolExecutor 的内部类,它同时持有:
- 一个真实的 Thread 实例(由线程工厂创建)
- 一个无限循环逻辑:while (task != null || (task = getTask()) != null)
- 执行任务的 run() 方法:先执行初始传入的任务,再不断调用 getTask() 从阻塞队列(如 LinkedBlockingQueue)中拉取新任务
这个循环就是复用发生的现场。线程启动后不会返回,也不会销毁,只是在队列上等待、获取、执行、再等待……整个生命周期内可串行处理成百上千个任务。
复用如何发生:三步闭环流程
当一个 Worker 启动并运行后,复用通过以下路径稳定维持:
- 任务执行完不退出:run() 方法末尾不 return,而是继续进入下一轮 getTask()
- 空闲时阻塞等待:getTask() 内部调用 queue.poll(keepAliveTime, unit) 或 queue.take(),线程挂起但不终止,资源(栈、TLS、JIT 编译代码)全部保留
- 唤醒即复用:一旦新任务入队或超时到期,线程被唤醒,立即执行新任务——无需重新分配栈、加载类、触发 GC 扫描线程局部对象
为什么能避免频繁创建:对比传统方式
不用线程池时,每提交一个任务就 new Thread(runnable).start(),每次都要:
- 向操作系统申请栈内存(默认约 1MB)
- 触发 JVM 线程注册与上下文初始化
- 执行线程调度器插入、上下文切换开销
- 任务结束还要回收资源、触发线程注销
而 Worker 模式下,这些开销只发生在 addWorker() 创建阶段;后续所有任务共享同一个 Thread 实例和运行时上下文,仅多一次 Runnable.run() 调用,成本几乎为零。
复用失效的常见原因
复用不是自动生效的,参数配置不当会直接破坏它:
- corePoolSize = 0:核心线程数为零,所有任务都走非核心路径,空闲超时后线程全被回收
- keepAliveTime 过短(如 1ms)+ maxPoolSize 较大:非核心线程刚建好就销毁,下次又要重建
- 使用无界队列(如 LinkedBlockingQueue 无参构造)且 corePoolSize 很小:大量任务积压在队列,核心线程永远满负荷,新任务无法及时触发复用调度
- 忘记清理 ThreadLocal:导致 Worker 线程无法被 GC,长期持有可能泄漏的对象,间接影响复用稳定性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











