线程池(Thread Pool)是一种基于池化思想管理线程 的并发工具,核心目标是复用线程资源、控制并发数量、降低资源开销 。其执行流程涉及任务提交、线程调度、任务排队、拒绝策略等多个环节,是Java并发编程中最常用的多线程管理方案(如ThreadPoolExecutor)。
一、线程池的核心组件
在理解执行流程前,需先明确线程池的核心组件及其作用:
| 组件 | 说明 | 
|---|---|
| 核心线程数(corePoolSize) | 线程池长期保留的最小线程数(即使空闲也不会被销毁,除非设置allowCoreThreadTimeOut)。 | 
| 最大线程数(maximumPoolSize) | 线程池允许创建的最大线程数(核心线程+非核心线程的总和)。 | 
| 任务队列(workQueue) | 当核心线程全忙时,新任务暂时存入的队列(如ArrayBlockingQueue、LinkedBlockingQueue)。 | 
| 非核心线程存活时间(keepAliveTime) | 非核心线程(超出核心线程数的线程)空闲多久后被回收的时间阈值。 | 
| 拒绝策略(RejectedExecutionHandler) | 当任务无法被核心线程、队列、非核心线程处理时,执行的回调策略(如丢弃任务、抛异常)。 | 
| 线程工厂(ThreadFactory) | 用于创建线程的工厂类(可自定义线程名称、优先级等)。 | 
二、线程池执行流程:从任务提交到执行
线程池的执行流程可分为5个阶段 ,核心逻辑是"优先复用核心线程→队列缓冲→创建非核心线程→触发拒绝策略"。以下是详细步骤:
阶段1:提交任务(submit/execute)
用户通过execute(Runnable task)或submit(Callable task)提交任务到线程池。线程池接收到任务后,立即进入调度逻辑。
阶段2:核心线程是否空闲?
线程池首先检查核心线程是否都在忙碌:
- 若有空闲的核心线程:直接由空闲核心线程执行任务(无需入队)。
 - 若核心线程全忙:进入阶段3(任务入队)。
 
阶段3:任务入队(workQueue.offer())
当核心线程全忙时,线程池会将新任务尝试存入任务队列:
- 队列未满:任务成功入队,等待核心线程空闲后从队列头部取出执行。
 - 队列已满:进入阶段4(创建非核心线程)。
 
阶段4:创建非核心线程(workerCount < maximumPoolSize)
若任务队列已满,线程池会检查当前线程总数(核心线程+非核心线程)是否小于maximumPoolSize:
- 是 :创建非核心线程(临时线程)执行该任务(非核心线程空闲超时后会被回收)。
 - 否:进入阶段5(触发拒绝策略)。
 
阶段5:触发拒绝策略(RejectedExecutionHandler)
当以下3个条件同时满足时,触发拒绝策略:
- 核心线程全忙;
 - 任务队列已满;
 - 线程总数已达
maximumPoolSize(无法创建新线程)。 
此时线程池会调用RejectedExecutionHandler处理任务,常见策略有4种:
| 策略 | 行为 | 
|---|---|
| AbortPolicy(默认) | 直接抛出RejectedExecutionException异常,拒绝任务。 | 
| CallerRunsPolicy | 由调用者(提交任务的线程)直接执行该任务("自己干")。 | 
| DiscardPolicy | 静默丢弃任务,不抛异常也不执行。 | 
| DiscardOldestPolicy | 丢弃队列中最旧的任务(队头任务),然后将新任务重新入队(尝试再次调度)。 | 
关键补充:核心线程的超时回收
若设置了allowCoreThreadTimeOut(true),核心线程在空闲超时(keepAliveTime)后也会被回收,此时线程池可能降级到0线程(仅保留任务队列中的任务)。
三、线程池架构图(ASCII版)
以下是线程池执行流程的架构图,展示了组件间的关系和任务流动路径:
            
            
              markdown
              
              
            
          
          +-------------------+          +------------------+          +------------------+          +------------------+  
|  提交任务          | -------> |  核心线程池       | -------> |  任务队列        | -------> |  非核心线程池     |  
| (execute/submit)  |          | (corePoolSize)   |          | (workQueue)      |          | (maxPoolSize-core)|  
+-------------------+          +------------------+          +------------------+          +------------------+  
         ↑                             ↓                              ↓                              ↓  
         |(核心线程空闲)             |(核心线程忙,队列未满)         |(队列满,线程数未达上限)      |(线程数达上限)              |  
         |                             |                              |                              |  
         |                             v                              v                              v  
         |                  +------------------+          +------------------+          +------------------+  
         |                  |  核心线程执行任务  |          |  任务入队等待     |          |  创建非核心线程   |  
         |                  | (Worker.run())   |          | (Queue.offer())  |          | (new Worker())    |  
         |                  +------------------+          +------------------+          +------------------+  
         |                                                                                           |  
         |                                                                                           v  
         |                                                                                  +------------------+  
         |                                                                                  |  触发拒绝策略      |  
         |                                                                                  | (RejectedHandler) |  
         |                                                                                  +------------------+  
         ↓                                                                                           |  
+-------------------+                                                                          +------------------+  
|  任务完成/异常      | <----------------------------------------------------------------------- |  任务执行/丢弃     |  
| (Future.get())    |                                                                          +------------------+  
+-------------------+  
### 图解说明:  
1. **任务提交**:用户通过`execute`提交任务,线程池开始调度。  
2. **核心线程执行**:若有空闲核心线程,直接执行任务(`Worker`线程通过`run()`方法处理任务)。  
3. **任务入队**:核心线程忙时,任务入队(如`ArrayBlockingQueue`),等待核心线程空闲后消费。  
4. **非核心线程创建**:队列满且线程数未达上限时,创建非核心线程执行任务。  
5. **拒绝策略**:队列满且线程数达上限时,触发拒绝策略处理任务。  
## 四、执行流程示例(以`ThreadPoolExecutor`为例)  
假设线程池配置:`corePoolSize=2`,`maximumPoolSize=5`,`workQueue=ArrayBlockingQueue(3)`,`rejectedPolicy=AbortPolicy`。  
1. **提交前2个任务**:核心线程(2个)空闲,直接执行。  
2. **提交第3-5个任务**:核心线程忙,任务依次入队(队列容量3,此时队列满)。  
3. **提交第6个任务**:核心线程忙+队列满,创建非核心线程(第3个线程)执行。  
4. **提交第7-9个任务**:继续创建非核心线程(第4、5个线程)执行。  
5. **提交第10个任务**:核心线程(2)+非核心线程(3)=5(达`maximumPoolSize`),队列已满(3),触发`AbortPolicy`,抛出异常。  
## 五、总结  
线程池的执行流程本质是**"资源分级利用"**:  
- 核心线程:长期驻留,减少线程创建开销;  
- 任务队列:缓冲突发流量,避免频繁创建线程;  
- 非核心线程:应对短期流量高峰,空闲后回收;  
- 拒绝策略:防止资源耗尽,保护系统稳定性。  
理解这一流程,能帮助开发者合理配置线程池参数(如`corePoolSize`、`workQueue`类型),避免"线程爆炸"或"任务堆积"问题,是高并发系统设计的必备技能。