FixedThreadPool适合稳定可预测的并发任务,核心线程数等于最大线程数且不回收空闲线程;需显式配置有界队列和拒绝策略,避免OOM;不可用Executors.newFixedThreadPool,应手动构建ThreadPoolExecutor实例。

FixedThreadPool 适合处理稳定、可预测的并发任务
它本质是线程数固定的 ThreadPoolExecutor,核心线程数 = 最大线程数,且不回收空闲线程。适合业务流量平稳、任务执行时间较均匀、资源需严格控制的场景,比如内部服务间的同步 RPC 调用、定时批处理中固定规模的数据分片任务。
不适合突发流量(会迅速堆积大量 LinkedBlockingQueue 任务,OOM 风险高),也不适合任务耗时差异极大(长任务阻塞线程,短任务被迫排队)。
FixedThreadPool 的队列和拒绝策略容易被忽略
它默认使用无界队列 new LinkedBlockingQueue,容量为 Integer.MAX_VALUE。这意味着:只要提交速度 > 执行速度,内存会持续增长,最终触发 OutOfMemoryError: Java heap space。
- 线上必须显式指定有界队列,例如
new LinkedBlockingQueue(1024) - 搭配合适的拒绝策略,如
new ThreadPoolExecutor.AbortPolicy()(抛RejectedExecutionException)或new ThreadPoolExecutor.CallerRunsPolicy()(由提交线程自己执行) - 不要依赖默认构造,应手动构建
ThreadPoolExecutor实例来获得完全控制权
与 CachedThreadPool、ScheduledThreadPool 的关键区别
FixedThreadPool 和 CachedThreadPool 看似都是“常用线程池”,但行为截然相反:
立即学习“Java免费学习笔记(深入)”;
-
CachedThreadPool:核心线程数为 0,空闲 60 秒即销毁,适合大量短期异步任务(如 I/O 回调),但可能创建过多线程导致 CPU 或句柄耗尽 -
ScheduledThreadPool:专为延迟/周期任务设计,底层用的是DelayedWorkQueue,不适用于普通 Runnable/Callable 提交 -
FixedThreadPool:唯一能保证“同时最多只有 N 个线程在跑”的标准池,适合需要强并发数限制的场景(如数据库连接数受限时的写入控制)
正确创建 FixedThreadPool 的推荐写法
避免使用 Executors.newFixedThreadPool(n) —— 它屏蔽了队列和拒绝策略配置能力,不符合生产要求。应直接使用 ThreadPoolExecutor 构造:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, // corePoolSize
4, // maximumPoolSize
0L, TimeUnit.MILLISECONDS, // keepAliveTime(固定池中无效,但需传)
new LinkedBlockingQueue<>(128), // 有界队列,防止 OOM
new ThreadFactoryBuilder()
.setNameFormat("fixed-pool-%d")
.build(),
new ThreadPoolExecutor.AbortPolicy() // 明确拒绝策略
);
注意:keepAliveTime 对固定池虽无实际作用(因为线程永不回收),但构造函数强制要求非负值;队列容量必须根据任务平均耗时、吞吐预期和堆内存综合评估,128 是常见起步值,不是 magic number。
真正难的不是选哪种池,而是清楚任务的吞吐特征、失败影响和资源边界——FixedThreadPool 只有在这些都明确的前提下,才成为安全选择。










