Java线程池运行流程分四步:1. 任务提交后,若线程数<corePoolSize则新建核心线程执行;2. 若已达corePoolSize且核心线程忙,则入阻塞队列;3. 队列满且线程数<maximumPoolSize时新建非核心线程执行;4. 队列满且线程数已达maximumPoolSize时触发拒绝策略。

Java线程池的运行流程,核心在于任务提交后的调度与执行逻辑,关键看线程数量、队列状态和拒绝策略这三者的协同作用。
任务提交后先尝试复用空闲线程
当调用 execute() 或 submit() 提交任务时,线程池不会立刻创建新线程。它首先检查当前运行的线程数是否小于 corePoolSize。如果是,就直接新建一个核心线程来执行该任务。
- 哪怕有空闲的核心线程,也会优先分配给新任务(因为线程池会主动唤醒等待中的线程)
- 这个阶段不涉及任务排队,也不触发拒绝策略
核心线程忙完就进入阻塞队列等待
如果当前线程数已达 corePoolSize,但所有核心线程都在忙,新任务就会被放入配置的阻塞队列(如 LinkedBlockingQueue、ArrayBlockingQueue 等)。
- 队列未满:任务成功入队,由空闲线程后续从队列中 take() 执行
- 队列已满:才考虑是否扩容——即判断当前线程数是否小于 maximumPoolSize
队列满且线程未达上限,就创建非核心线程
当队列已满,同时当前线程总数 ,线程池会新建一个“非核心线程”来立即执行该任务。
立即学习“Java免费学习笔记(深入)”;
- 这类线程在空闲超过 keepAliveTime 后会被自动回收(核心线程默认不回收,除非设置了 allowCoreThreadTimeOut(true))
- 非核心线程只在高负载时临时补充,不是长期驻留的
超出最大容量,触发拒绝策略
如果队列已满、线程数已达 maximumPoolSize,再提交任务就会被拒绝。此时执行 RejectedExecutionHandler:
- AbortPolicy(默认):抛出 RejectedExecutionException
- CallerRunsPolicy:由提交任务的线程自己执行该任务(可缓解压力)
- DiscardPolicy:静默丢弃任务
- DiscardOldestPolicy:丢弃队列头任务,再尝试提交当前任务
基本上就这些。整个流程不是固定顺序执行,而是动态根据资源水位实时决策,理解 core/max/queue 三者的关系,就抓住了线程池行为的主干。











