主题切换
线程池种类
一、概述
java.util.concurrent.Executors 工具类提供四种常用线程池,底层均基于 ThreadPoolExecutor 实现,各自参数、队列、适用场景不同。
二、四种内置线程池详解
1. newFixedThreadPool 固定线程池
底层构造:
java
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}参数特征:
- corePoolSize = maximumPoolSize = nThreads,无临时急救线程;
- 阻塞队列:无界
LinkedBlockingQueue,容量Integer.MAX_VALUE。 适用场景:任务量可控、执行耗时较长,需要限制并发峰值。 ⚠️ 风险:任务大量堆积会无限占用内存,引发OOM。
2. newSingleThreadExecutor 单线程池
底层构造:
java
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}参数特征:
- 核心线程、最大线程均为1,全程单线程串行执行;
- 阻塞队列:无界
LinkedBlockingQueue。 适用场景:任务必须严格按FIFO顺序执行,不允许并发。 ⚠️ 风险:无界队列堆积任务,大量任务会OOM。
3. newCachedThreadPool 可缓存线程池
底层构造:
java
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}参数特征:
- corePoolSize=0,无常驻核心线程;
- maximumPoolSize=Integer.MAX_VALUE,线程几乎无上限;
- 空闲线程存活60秒,超时自动回收;
- 队列:
SynchronousQueue,不存储任务,任务直接转交线程。 适用场景:任务密集、单任务执行时间短,大量短时异步任务。 ⚠️ 风险:瞬间海量任务会创建大量线程,耗尽CPU/内存资源。
4. newScheduledThreadPool 定时延迟线程池
底层实现 ScheduledThreadPoolExecutor,继承 ThreadPoolExecutor:
java
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}参数特征:
- 自定义核心线程数,最大线程无上限;
- 阻塞队列:
DelayedWorkQueue延时优先级队列,按任务执行时间排序; - 支持延迟执行、周期性定时任务。 适用场景:定时任务、延时任务、轮询调度业务。
三、总结对比
- newFixedThreadPool:固定并发数,长耗时任务,限制峰值;
- newSingleThreadExecutor:单线程串行,保证任务有序执行;
- newCachedThreadPool:短时密集任务,自动回收空闲线程;
- newScheduledThreadPool:支持延迟、周期定时调度。
四、生产规范提醒
参考阿里《Java开发手册-嵩山版》【强制】规范:禁止使用Executors创建线程池,必须手动实例化ThreadPoolExecutor,规避资源耗尽风险,具体弊端如下:
- newFixedThreadPool、newSingleThreadExecutor 底层队列是无界LinkedBlockingQueue,队列容量为Integer.MAX_VALUE,高并发下大量任务持续堆积,会占用大量堆内存,最终触发OOM内存溢出。
- newCachedThreadPool、newScheduledThreadPool 最大线程数设置为Integer.MAX_VALUE,突发海量任务时会无限新建线程,大量线程抢占CPU、内存,导致服务器资源耗尽、服务不可用。
正确生产写法
手动指定七大参数,使用有界阻塞队列,配置合理最大线程与拒绝策略:
java
ExecutorService pool = new ThreadPoolExecutor(
8,
16,
60L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), // 有界队列
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);五、面试简答
问:Executors提供哪四种线程池,各自特点?为什么生产不建议使用? 答:
- Fixed固定线程池,线程数量固定,无界队列,限制并发;
- Single单线程池,仅一条工作线程,任务串行有序执行;
- Cached缓存线程池,核心线程0,无上限临时线程,60秒空闲回收,无队列缓冲;
- Scheduled定时线程池,专用延时优先级队列,支持延迟、周期任务。 禁止使用原因:Fixed、Single无界队列堆积任务会OOM;Cached、Scheduled最大线程无上限,突发流量创建海量线程耗尽服务器资源;线上需手动构造ThreadPoolExecutor,配置有界队列、可控最大线程。