线程池类型

线程池类型

Executors 工厂类

Java 通过 Executors 工厂类提供了几种常用的线程池实现:

1
2
3
4
5
6
7
8
9
┌─────────────────────────────────────────────────────────────────┐
│ Executors │
├─────────────────────────────────────────────────────────────────┤
newFixedThreadPool() → 固定大小线程池 │
newCachedThreadPool() → 缓存线程池 │
newSingleThreadExecutor() → 单线程池 │
newScheduledThreadPool() → 定时任务线程池 │
newWorkStealingPool() → 工作窃取线程池 (Java 8+) │
└─────────────────────────────────────────────────────────────────┘

1. FixedThreadPool(固定大小线程池)

特点

  • 核心线程数 = 最大线程数 = 固定值
  • 使用无界队列 LinkedBlockingQueue
  • 线程不会被回收

源码分析

1
2
3
4
5
6
7
8
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(
nThreads, // corePoolSize
nThreads, // maximumPoolSize(相同)
0L, TimeUnit.MILLISECONDS, // 不回收
new LinkedBlockingQueue<Runnable>() // 无界队列
);
}

使用场景

场景 说明
CPU 密集型任务 线程数 = CPU 核心数 + 1
负载稳定的服务 已知并发量,固定线程数

示例

1
2
3
4
5
6
7
8
9
// 创建固定 4 个线程的线程池
ExecutorService executor = Executors.newFixedThreadPool(4);

for (int i = 0; i < 10; i++) {
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " 执行任务");
});
}
executor.shutdown();

风险提示

OOM 风险:使用无界队列,任务堆积可能导致内存溢出


2. CachedThreadPool(缓存线程池)

特点

  • 核心线程数 = 0
  • 最大线程数 = Integer.MAX_VALUE(几乎无限)
  • 使用 SynchronousQueue(不存储任务,直接传递)
  • 空闲线程 60 秒后回收

源码分析

1
2
3
4
5
6
7
8
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(
0, // corePoolSize = 0
Integer.MAX_VALUE, // maximumPoolSize = 无限
60L, TimeUnit.SECONDS, // 60秒回收
new SynchronousQueue<Runnable>() // 直接传递
);
}

使用场景

场景 说明
短时异步任务 执行时间短,任务量波动大
IO 密集型任务 大量等待,需要更多线程

示例

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

// 模拟突发大量短任务
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
System.out.println(Thread.currentThread().getName());
try { Thread.sleep(100); } catch (InterruptedException e) {}
});
}
executor.shutdown();

风险提示

线程爆炸:任务提交速度 > 处理速度时,会创建大量线程,可能导致系统崩溃


3. SingleThreadExecutor(单线程池)

特点

  • 只有 1 个线程
  • 使用无界队列
  • 保证任务顺序执行
  • 线程异常终止后会创建新线程

源码分析

1
2
3
4
5
6
7
8
9
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService(
new ThreadPoolExecutor(
1, 1, // 只有1个线程
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()
)
);
}

使用场景

场景 说明
顺序执行任务 日志写入、消息处理
单线程安全 避免并发问题

示例

1
2
3
4
5
6
7
8
9
ExecutorService executor = Executors.newSingleThreadExecutor();

// 任务按顺序执行
executor.submit(() -> System.out.println("任务1"));
executor.submit(() -> System.out.println("任务2"));
executor.submit(() -> System.out.println("任务3"));
// 输出顺序一定是:任务1 → 任务2 → 任务3

executor.shutdown();

风险提示

OOM 风险:同 FixedThreadPool,无界队列可能导致内存溢出


4. ScheduledThreadPool(定时任务线程池)

特点

  • 支持定时执行周期执行
  • 使用 DelayedWorkQueue(延迟队列)

源码分析

1
2
3
4
5
6
7
8
9
10
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}

// ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}

核心方法

方法 说明
schedule() 延迟执行一次
scheduleAtFixedRate() 固定频率执行(不考虑任务耗时)
scheduleWithFixedDelay() 固定延迟执行(任务结束后延迟)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

// 1. 延迟 3 秒执行
scheduler.schedule(() -> {
System.out.println("延迟3秒执行");
}, 3, TimeUnit.SECONDS);

// 2. 固定频率:每 2 秒执行一次(从上次开始时间算)
scheduler.scheduleAtFixedRate(() -> {
System.out.println("固定频率执行: " + System.currentTimeMillis());
}, 0, 2, TimeUnit.SECONDS);

// 3. 固定延迟:每次执行完后等 2 秒再执行
scheduler.scheduleWithFixedDelay(() -> {
System.out.println("固定延迟执行");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
}, 0, 2, TimeUnit.SECONDS);

scheduleAtFixedRate vs scheduleWithFixedDelay

1
2
3
4
5
6
7
8
scheduleAtFixedRate (period=2s, 任务耗时1s):
|--任务--| |--任务--| |--任务--|
0 1 2 3 4 5 (秒)

scheduleWithFixedDelay (delay=2s, 任务耗时1s):
|--任务--| |--任务--| |--任务--|
0 1 2 3 4 5 6 7 (秒)
└──2s延迟──┘ └──2s延迟──┘

5. WorkStealingPool(工作窃取线程池)

特点(Java 8+)

  • 基于 ForkJoinPool 实现 ^forkjoinpool
  • 每个线程有自己的双端队列
  • 空闲线程会窃取其他线程队列的任务
  • 默认线程数 = CPU 核心数

源码分析

1
2
3
4
5
6
7
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool(
Runtime.getRuntime().availableProcessors(), // CPU核心数
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true
);
}

工作窃取原理

1
2
3
4
5
6
7
线程1的队列:  [任务A] [任务B] [任务C] [任务D]
↑ 从头部取任务执行

线程2的队列: [空]
↑ 自己队列空了,从线程1队列尾部窃取

结果: 线程2窃取任务D执行

使用场景

场景 说明
递归任务 分治算法、树遍历
并行计算 大数据处理、并行流

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
ExecutorService executor = Executors.newWorkStealingPool();

List<Callable<Integer>> tasks = new ArrayList<>();
for (int i = 0; i < 100; i++) {
final int num = i;
tasks.add(() -> {
Thread.sleep(100);
return num * num;
});
}

// 并行执行所有任务
List<Future<Integer>> results = executor.invokeAll(tasks);

线程池对比总结

类型 核心线程 最大线程 队列 适用场景
Fixed n n 无界 LinkedBlockingQueue CPU密集、负载稳定
Cached 0 MAX SynchronousQueue 短任务、IO密集
Single 1 1 无界 LinkedBlockingQueue 顺序执行
Scheduled n MAX DelayedWorkQueue 定时/周期任务
WorkStealing CPU核心数 - 双端队列 递归/并行计算

最佳实践:自定义线程池

阿里巴巴 Java 开发手册:禁止使用 Executors 创建线程池,应通过 ThreadPoolExecutor 手动创建

原因

工厂方法 风险
FixedThreadPool 无界队列可能 OOM
SingleThreadExecutor 无界队列可能 OOM
CachedThreadPool 最大线程数无限,可能创建过多线程
ScheduledThreadPool 最大线程数无限

推荐写法

1
2
3
4
5
6
7
8
9
10
11
// ✅ 推荐:手动创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, // 核心线程数
20, // 最大线程数
60L, TimeUnit.SECONDS, // 空闲存活时间
new ArrayBlockingQueue<>(100), // 有界队列
new ThreadFactoryBuilder() // 自定义线程名(Guava)
.setNameFormat("业务线程-%d")
.build(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);

线程数设置建议

任务类型 线程数公式 说明
CPU 密集型 N + 1 N = CPU 核心数
IO 密集型 2N 或 N * (1 + W/C) W=等待时间,C=计算时间
1
2
// 获取 CPU 核心数
int cpuCores = Runtime.getRuntime().availableProcessors();

相关链接

  • 上一篇:02-线程池原理
  • 下一篇:04-ForkJoinPool
  • 线程池简介:01-线程池简介

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