Java线程池通过预创建、循环取任务和按需回收实现线程复用,Worker线程串行执行多个任务;核心线程默认永驻,非核心线程空闲超时退出;任务提交与线程调度解耦。

Java 线程池通过“预创建 + 循环执行 + 按需回收”的方式实现线程复用,核心不是让一个线程同时跑多个任务,而是让同一个线程对象**串行执行多个任务**,避免反复创建和销毁线程的系统开销。
Worker 线程内置无限循环取任务
每个工作线程(Worker)启动后,会进入一个 while 循环:
while (task != null || (task = getTask()) != null) { task.run(); }
它不会执行完一个任务就退出,而是持续从阻塞队列(如 LinkedBlockingQueue 或 SynchronousQueue)中拉取下一个任务。队列为空时,线程会阻塞等待(如 take())或超时等待(如 poll(timeout)),而不是终止自己。
核心线程长期存活,非核心线程按需回收
线程池对不同线程采用差异化生命周期管理:
- 核心线程(数量 ≤ corePoolSize)默认永不超时,即使空闲也保留在池中,随时响应新任务
- 非核心线程在空闲超过 keepAliveTime 后自动退出循环、释放资源、终止自身
- allowCoreThreadTimeOut 设为 true 时,核心线程也会受 keepAliveTime 约束
任务提交与线程解耦,调度由池统一控制
你调用 execute() 或 submit() 提交任务时,并不指定由哪个线程执行。线程池内部按策略分配:
- 当前线程数
- 否则先尝试入队;入队成功 → 等待已有线程从队列取任务
- 队列满且线程数
- 否则触发拒绝策略
这种松耦合设计,使得线程可以被任意任务复用,无需绑定上下文。
立即学习“Java免费学习笔记(深入)”;
必须注意 ThreadLocal 的清理
由于线程生命周期远长于单个任务,若任务中使用了 ThreadLocal 存储上下文(如用户 ID、事务信息),必须在任务结束前显式调用 remove():
- 不 remove → 可能导致内存泄漏(引用无法回收)
- 不 remove → 后续任务可能读到上一个任务残留的数据(上下文污染)
- 建议在 finally 块或 afterExecute() 回调中统一清理


















