ThreadPoolExecutor 的扩容是按需触发的被动响应机制,严格遵循“核心线程→队列→非核心线程”三级顺序,仅当核心线程全忙且任务无法入队时,才创建非核心线程直至 maximumPoolSize。

ThreadPoolExecutor 的扩容不是“主动伸缩”,而是按需触发的被动响应机制,整个流程严格遵循“核心线程 → 队列 → 非核心线程”的三级任务承接顺序。
扩容触发的前提条件
扩容只在以下两个条件**同时满足**时发生:
- 当前运行中的线程数 ≤ corePoolSize,但新任务提交后,**核心线程全忙**(无空闲);
- 任务无法立即入队——即所用阻塞队列已满(对有界队列如 ArrayBlockingQueue)或拒绝策略判定需绕过队列(如 SynchronousQueue 本质无容量)。
注意:LinkedBlockingQueue 默认无界(容量 Integer.MAX_VALUE),此时队列几乎永不“满”,扩容永远不会触发——所有超额任务都堆积在队列中,线程数始终卡在 corePoolSize。
扩容的实际执行动作
当满足触发条件,线程池会尝试启动一个**非核心线程**(而非增加核心线程数)来直接执行新任务,具体步骤如下:
立即学习“Java免费学习笔记(深入)”;
- 调用
addWorker(command, false):第二个参数false表明创建的是非核心线程; - 该线程启动后立即执行传入的 task,不经过队列;
- 线程执行完毕后进入空闲状态,若空闲时间超过
keepAliveTime,且当前总线程数 >corePoolSize,则被回收。
这个过程是“任务驱动”的:每有一个无法入队的新任务,就尝试新建一个非核心线程,直到总线程数达到 maximumPoolSize。
扩容的边界与终止
扩容不会无限进行,受两个硬性限制:
-
数量上限:线程总数不能超过
maximumPoolSize,达到后不再新建线程; - 队列类型决定是否走这一步:SynchronousQueue 强制走扩容路径(因无缓冲);ArrayBlockingQueue 在满时才触发;无界队列则跳过扩容,直接触发拒绝策略(当线程已达 max 且队列仍可加——实际不会发生,但逻辑上如此)。
一旦线程数达到 maximumPoolSize 且队列也满,后续任务将交由 RejectedExecutionHandler 处理,默认策略是抛出 RejectedExecutionException。
动态调整核心线程数 ≠ 扩容机制本身
调用 setCorePoolSize(n) 是外部干预行为,不属于 ThreadPoolExecutor 内置的自动扩容流程。它会:
- 增大时:若队列非空,会尝试用新增的核心线程从队列中取任务执行;
- 减小时:仅对当前空闲的核心线程生效,正在运行的线程不受影响,也不会中断。
这种调整属于运维或监控系统驱动的“人工扩容/缩容”,和线程池自身基于任务压力的自动扩容逻辑相互独立。


















