java线程池不直接调度cpu线程,由os以抢占式时间片轮转调度;其核心是标准化任务排队、扩容、执行与失败处理逻辑。提交任务时先比对活跃线程数与corepoolsize,不足则新建线程(含空闲也不复用);达corepoolsize后入队等待复用;队列满且线程数未超maximumpoolsize才扩容非核心线程;最终拒绝任务触发策略或自定义钩子。

Java线程池本身不直接实现CPU级线程调度,它负责的是任务级的分发与管理;真正的线程执行调度由操作系统完成,采用抢占式时间片轮转机制。线程池的核心价值在于把“任务如何排队、何时扩容、谁来执行、失败怎么处理”这一整套逻辑标准化、可控化。
任务提交与核心线程判断
当调用 execute() 或 submit() 提交任务时,线程池第一件事是检查当前活跃线程数是否小于 corePoolSize。只要没达到这个数,就立即新建线程执行任务——哪怕已有空闲线程也不会复用,这是核心线程“宁可多建、不可闲置”的设计原则。
- 新建线程会绑定一个 Worker 对象,该对象封装了线程和任务循环逻辑
- 核心线程默认长期存活,除非显式设置 allowCoreThreadTimeOut(true)
- 此阶段不涉及队列,也不看优先级,纯数量驱动
任务入队与线程复用
一旦活跃线程数 ≥ corePoolSize,新任务不再新建线程,而是尝试加入 workQueue(如 LinkedBlockingQueue、ArrayBlockingQueue)。队列未满则成功入队,等待空闲线程主动取走执行。
- 线程从队列中获取任务使用的是 take()(阻塞式)或 poll(timeout)(带超时),取决于队列类型
- 此时线程复用真正开始:一个核心线程可能连续执行多个排队任务
- 注意:队列容量设置过大(如无界 LinkedBlockingQueue)会导致线程数始终卡在 corePoolSize,高峰时任务积压内存溢出
动态扩容与最大线程边界
只有当队列已满,且当前线程总数 仍小于 maximumPoolSize 时,线程池才会创建非核心线程执行新任务。
- 非核心线程只在负载高峰期临时补充,空闲超过 keepAliveTime 后自动销毁
- 扩容行为不是“按需触发”,而是“队列满 + 线程未达上限”双重条件同时满足才发生
- 若 maximumPoolSize 设置过高(如 Integer.MAX_VALUE),配合无界队列,可能导致线程数失控
拒绝策略与自定义钩子介入点
当队列满 + 线程已达 maximumPoolSize,新任务无法接纳,线程池启动 RejectedExecutionHandler。四种内置策略各有适用场景:
- AbortPolicy(默认):抛出 RejectedExecutionException,适合强一致性要求场景
- CallerRunsPolicy:由提交任务的线程自己执行,可自然降速,缓解压力
- DiscardPolicy:静默丢弃,适合允许丢失的任务(如日志上报)
- DiscardOldestPolicy:丢弃队首任务,再尝试提交当前任务
此外,可通过重写 beforeExecute() 和 afterExecute() 在任务执行前后插入监控、上下文初始化或异常归因逻辑,不干扰主流程但增强可观测性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











