线程池原理

线程池原理

核心参数(7大参数)

ThreadPoolExecutor 是线程池的核心实现类,其构造函数包含 7 个关键参数:

1
2
3
4
5
6
7
8
9
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 空闲线程存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)

参数详解

参数 说明 建议
corePoolSize 核心线程数,即使空闲也不会被回收 CPU密集型:N+1,IO密集型:2N 👉详解
maximumPoolSize 线程池最大线程数 根据业务峰值设置
keepAliveTime 非核心线程空闲存活时间 一般 60s
unit keepAliveTime 的时间单位 TimeUnit.SECONDS
workQueue 任务等待队列 有界队列更安全
threadFactory 创建线程的工厂,可自定义线程名 建议自定义便于排查
handler 队列满且线程数达到最大时的拒绝策略 根据业务选择

工作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
      ┌─────────────────┐
│ 提交任务 │
└────────┬────────┘


┌──────────────────────────────┐
│ 核心线程数 < corePoolSize? │
└──────────────┬───────────────┘
YES │ │ NO
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ 创建核心线程 │ │ 任务队列未满? │
│ 执行任务 │ └────────┬────────┘
└─────────────┘ YES │ │ NO
▼ ▼
┌─────────┐ ┌──────────────────┐
│ 入队等待 │ │ 线程数 < maxSize? │
└─────────┘ └────────┬─────────┘
YES │ │ NO
▼ ▼
┌─────────┐ ┌─────────┐
│创建非核心│ │ 拒绝策略 │
│线程执行 │ └─────────┘
└─────────┘

流程总结

  1. 核心线程优先:任务来了先看核心线程是否已满
  2. 队列缓冲:核心线程满了,任务进入队列等待
  3. 扩容线程:队列满了,创建非核心线程处理 👉详解 ^expand-thread
  4. 拒绝任务:线程数达到最大且队列满,执行拒绝策略

注意:不是先扩容线程再入队,而是先入队再扩容


任务队列类型

队列类型 特点 适用场景
ArrayBlockingQueue 有界数组队列,FIFO 控制资源消耗,推荐使用
LinkedBlockingQueue 可选有界链表队列,默认无界 任务量可控时使用
SynchronousQueue 不存储元素,直接传递 CachedThreadPool 使用
PriorityBlockingQueue 优先级队列,无界 需要任务优先级时
DelayQueue 延迟队列 定时任务场景
1
2
// 推荐:使用有界队列
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(100);

四种拒绝策略

当任务无法被执行时(队列满 + 线程数达到最大),触发拒绝策略:

策略 行为 适用场景
AbortPolicy 抛出 RejectedExecutionException 默认策略,快速失败
CallerRunsPolicy 由提交任务的线程执行 不丢弃任务,降级处理
DiscardPolicy 静默丢弃任务 允许丢失的场景
DiscardOldestPolicy 丢弃队列最老的任务,重新提交 新任务优先级更高
1
2
3
4
5
6
7
// 自定义拒绝策略示例
RejectedExecutionHandler customHandler = (r, executor) -> {
// 记录日志
log.warn("任务被拒绝: {}", r.toString());
// 可选:持久化到数据库/MQ,后续重试
saveToDatabase(r);
};

线程池状态(5种状态)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
┌──────────┐
│ RUNNING │ ← 初始状态,接收新任务,处理队列任务
└────┬─────┘
shutdown()

┌──────────┐
│ SHUTDOWN │ ← 不接收新任务,继续处理队列任务
└────┬─────┘
│ 队列为空 && 工作线程为0

┌──────────┐
│ TIDYING │ ← 所有任务终止,工作线程为0
└────┬─────┘
terminated() 执行完成

┌──────────────┐
│ TERMINATED │ ← 线程池彻底终止
└──────────────┘

┌──────────┐
│ RUNNING │
└────┬─────┘
shutdownNow()

┌──────────┐
STOP │ ← 不接收新任务,中断正在执行的任务,清空队列
└────┬─────┘
│ 工作线程为0

┌──────────┐
│ TIDYING │
└──────────┘

状态转换方法

方法 说明
shutdown() 温和关闭,等待已提交任务完成
shutdownNow() 立即关闭,尝试中断执行中的任务,返回未执行的任务列表
awaitTermination() 阻塞等待线程池终止
1
2
3
4
5
6
7
8
9
10
// 优雅关闭线程池
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}

线程池监控

1
2
3
4
5
6
7
8
9
10
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);

// 监控指标
System.out.println("核心线程数: " + executor.getCorePoolSize());
System.out.println("最大线程数: " + executor.getMaximumPoolSize());
System.out.println("当前线程数: " + executor.getPoolSize());
System.out.println("活跃线程数: " + executor.getActiveCount());
System.out.println("队列任务数: " + executor.getQueue().size());
System.out.println("已完成任务: " + executor.getCompletedTaskCount());
System.out.println("总任务数: " + executor.getTaskCount());

相关链接

  • 上一篇:01-线程池简介
  • 下一篇:03-线程池类型

线程池原理
https://zmmmmy.github.io/2026/01/10/线程池原理/
作者
ZhiMy
发布于
2026年1月10日
许可协议