线程池的种类、区别与使用场景¶
一、FixedThreadPool¶
- core = max = 10。
- 队列:LinkedBlockingQueue(无界)。
- 固定线程数,任务排队。
场景:CPU 密集型,线程数 = CPU 核数。
坑:无界队列,任务多了 OOM。
二、CachedThreadPool¶
- core = 0,max = Integer.MAX_VALUE。
- 队列:SynchronousQueue(不存)。
- 60 秒空闲回收。
- 来了任务就开新线程。
场景:IO 密集,短任务。
坑:线程数无上限,可能创建过多线程 OOM。
三、SingleThreadExecutor¶
- core = max = 1。
- 无界队列。
- 单线程串行执行。
场景:需要顺序执行的任务。
坑:无界队列 OOM。
四、ScheduledThreadPool¶
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
pool.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
- 定时/周期任务。
- DelayedWorkQueue。
场景:定时任务(替代 Timer)。
五、对比¶
| 线程池 | 核心 | 最大 | 队列 | 场景 |
|---|---|---|---|---|
| Fixed | n | n | 无界 | CPU 密集 |
| Cached | 0 | ∞ | Synchronous | IO 密集 |
| Single | 1 | 1 | 无界 | 顺序执行 |
| Scheduled | n | ∞ | Delayed | 定时任务 |
六、生产建议¶
不要用 Executors,手动 new ThreadPoolExecutor:
ThreadPoolExecutor pool = new ThreadPoolExecutor(
10, 20, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100),
new ThreadFactoryBuilder().setNameFormat("biz-pool-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
原因: - 明确有界队列,避免 OOM。 - 明确最大线程数。 - 自定义线程名,方便排查。 - 明确拒绝策略。
七、线程数怎么设¶
- CPU 密集:核数 + 1。
- IO 密集:核数 × (1 + 等待时间/计算时间)。
- 实际压测调优。
阿里规约
线程池不允许用 Executors,要用 ThreadPoolExecutor,明确参数,避免 OOM。