Java线程池的工作原理
graph TD
A[提交任务] --> B{核心线程池是否已满?}
B -- 未满 --> C[创建核心线程执行任务]
B -- 已满 --> D{任务队列是否已满?}
D -- 未满 --> E[任务加入阻塞队列等待]
D -- 已满 --> F{线程池是否达到最大线程数?}
F -- 未达到 --> G[创建非核心线程执行任务]
F -- 已达到 --> H[触发拒绝策略]
classDef green fill:#D5E8D4,stroke:#82B366;
classDef orange fill:#F8CECC,stroke:#B85450;
classDef blue fill:#DAE8FC,stroke:#6C8EBF;
class A,B,D,F blue
class C,G green
class H orange
工作原理详细流程:
-
任务提交
- 当通过
execute()或submit()方法提交新任务时,线程池开始处理
- 当通过
-
核心线程检查
- 检查当前运行的核心线程数是否小于
corePoolSize - 若未满:创建新核心线程立即执行任务(即使有空闲线程也会创建新线程)
- 若已满:进入下一步
- 检查当前运行的核心线程数是否小于
-
任务队列检查
- 尝试将任务加入阻塞队列(如
LinkedBlockingQueue) - 若队列未满:任务进入队列等待空闲线程处理
- 若队列已满:进入下一步
- 尝试将任务加入阻塞队列(如
-
最大线程数检查
- 检查当前总线程数是否小于
maximumPoolSize - 若未达到:创建临时非核心线程立即执行任务
- 若已达到:进入拒绝流程
- 检查当前总线程数是否小于
-
拒绝策略处理
- 触发配置的拒绝策略(默认4种):
AbortPolicy:抛出RejectedExecutionException(默认策略)CallerRunsPolicy:由提交任务的线程直接执行DiscardPolicy:静默丢弃任务DiscardOldestPolicy:丢弃队列最前面的任务并重试
- 触发配置的拒绝策略(默认4种):
关键组件说明:
| 组件 | 作用 | 配置参数 |
|---|---|---|
| 核心线程池 | 常驻线程,处理常规任务 | corePoolSize |
| 任务阻塞队列 | 缓存待处理任务 | workQueue(如Array/LinkedBlockingQueue) |
| 最大线程池 | 应急线程(临时创建) | maximumPoolSize |
| 线程存活时间 | 非核心线程空闲回收时间 | keepAliveTime + unit |
| 线程工厂 | 定制线程创建行为 | ThreadFactory |
| 拒绝策略 | 处理过载任务 | RejectedExecutionHandler |
工作特点:
- 线程复用:通过
Worker类包装线程,循环从阻塞队列获取任务执行 - 资源回收:非核心线程空闲超过
keepAliveTime后自动回收 - 优雅关闭:
shutdown():停止接收新任务,继续处理队列任务shutdownNow():尝试中断所有线程,返回未处理任务列表
最佳实践:
- IO密集型任务:建议
corePoolSize = CPU核数*2- CPU密集型任务:建议
corePoolSize = CPU核数+1- 使用
ThreadPoolExecutor构造函数而非Executors工厂方法,避免资源耗尽风险