大家好,我是G探险者!
在并发编程中,线程池 是最常用的工具之一,它能够管理线程的生命周期、提高线程复用率、避免频繁创建和销毁线程带来的开销。Java 从 JDK 5 开始通过 java.util.concurrent
包提供了丰富的线程池实现。
本文将从 创建方式 和 应用场景 两方面来总结常见线程池。
1. 通过 Executors
工厂方法创建
Executors
提供了多种静态工厂方法,适合快速上手。常见的有:
(1) FixedThreadPool --- 固定大小线程池
java
ExecutorService pool = Executors.newFixedThreadPool(5);
-
特点 :线程数固定;任务超过时进入 无界队列;线程数不会变化。
-
适用场景:
- 稳定的后台任务处理
- 比如日志处理、批量数据入库
(2) CachedThreadPool --- 缓存线程池
java
ExecutorService pool = Executors.newCachedThreadPool();
-
特点:无核心线程;最大线程数几乎无限;空闲线程 60s 后回收。
-
适用场景:
- 大量 短期异步任务
- 比如 RPC 调用、并发 I/O
(3) SingleThreadExecutor --- 单线程池
java
ExecutorService pool = Executors.newSingleThreadExecutor();
-
特点:只有一个线程,所有任务顺序执行。
-
适用场景:
- 对执行顺序有严格要求的场景
- 比如日志写入、顺序文件处理
(4) ScheduledThreadPool --- 定时任务线程池
java
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
-
特点:支持定时和周期性任务。
-
适用场景:
- 定时任务、周期任务
- 比如心跳检测、定时调度、超时检测
(5) WorkStealingPool --- 工作窃取线程池 (JDK 1.8+)
java
ExecutorService pool = Executors.newWorkStealingPool();
-
特点 :基于
ForkJoinPool
;任务会被拆分成小任务并行执行;支持线程间任务"窃取"。 -
适用场景:
- 大任务拆分并行计算
- 比如递归算法、分块计算、图像处理
2. 通过 ThreadPoolExecutor
自定义创建
在实际生产环境中,更推荐直接使用 ThreadPoolExecutor
来精细化控制线程池。
java
ThreadPoolExecutor pool = new ThreadPoolExecutor(
4, // 核心线程数
10, // 最大线程数
60, TimeUnit.SECONDS, // 空闲线程存活时间
new ArrayBlockingQueue<>(100), // 有界任务队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
-
优势:
- 可控性强,避免
Executors
默认无界队列 / 无限线程带来的风险 - 可以选择 有界队列,防止 OOM
- 可以定制 拒绝策略:丢弃、调用者执行、抛异常、丢弃最旧任务
- 可控性强,避免
-
适用场景:
- 高并发、高稳定性要求的生产环境
- 比如 Web 服务请求处理、MQ 消费者、业务异步任务调度
3. ForkJoinPool (分治任务池)
java
ForkJoinPool pool = new ForkJoinPool();
-
特点:
- JDK 7 引入,适合 大任务拆分成子任务并行执行,最后合并结果
- 使用 工作窃取算法 平衡负载
-
适用场景:
- CPU 密集型计算任务
- 比如矩阵运算、MapReduce、并行递归
4. 线程池应用场景总结
线程池类型 | 适用场景 |
---|---|
FixedThreadPool | 稳定的后台任务(日志、批量任务) |
CachedThreadPool | 短期异步任务(RPC 调用、I/O) |
SingleThreadExecutor | 顺序性任务(日志写入、文件处理) |
ScheduledThreadPool | 定时调度(心跳、超时检测) |
WorkStealingPool | 大任务拆分并行(递归、分块计算) |
ForkJoinPool | CPU 密集型计算(科学计算、图像处理) |
ThreadPoolExecutor | 高并发业务处理(Web 请求、MQ 消费) |
5. 小结
- 学习阶段可以用
Executors
简化开发; - 生产环境推荐使用 自定义 ThreadPoolExecutor,明确控制线程数、队列大小和拒绝策略;
- 不同线程池适用的场景差别很大,合理选择能大幅提升系统性能与稳定性。