ThreadPoolExecutor 的 7 个核心参数共同决定线程池行为:corePoolSize(常驻线程数)、maximumPoolSize(最大线程数)、keepAliveTime 及 unit(空闲线程存活时间)、workQueue(任务队列)、threadFactory(线程工厂)、handler(拒绝策略),缺一不可。

ThreadPoolExecutor 是 Java 中最灵活的线程池实现,它允许你精确控制线程池的行为。所谓“7 个核心参数”,其实是指构造函数中可配置的 7 个关键字段——它们共同决定了线程池的运行策略、资源边界和任务调度逻辑。
corePoolSize:常驻线程数
这是线程池中始终维持的最小线程数量,即使这些线程处于空闲状态也不会被回收(除非设置了 allowCoreThreadTimeOut)。它代表了线程池的“基础运力”。
- 设置过小:任务排队增多,响应变慢;
- 设置过大:空闲线程占用资源,可能引发上下文切换开销;
- 常见做法:CPU 密集型任务设为 CPU 核心数,IO 密集型可适当放大(如核数 × 2)。
maximumPoolSize:最大线程数
当任务持续涌入、队列已满时,线程池会新建线程执行任务,直到总线程数达到该值。它限制了线程池的“峰值并发能力”。
- 必须 ≥ corePoolSize,否则抛出 IllegalArgumentException;
- 若使用无界队列(如 LinkedBlockingQueue),该参数实际不会生效(因为永远不会触发扩容);
- 配合有界队列(如 ArrayBlockingQueue)才能真正起作用。
keepAliveTime & unit:空闲线程存活时间
超出 corePoolSize 的线程,在空闲超过 keepAliveTime 后会被终止。unit 指定时间单位(如 TimeUnit.SECONDS)。
立即学习“Java免费学习笔记(深入)”;
- 仅对非核心线程生效(即 > corePoolSize 的那部分);
- 若设置了 allowCoreThreadTimeOut(true),则核心线程也适用此规则;
- 建议设为几十秒到几分钟,避免频繁创建/销毁线程。
workQueue:任务等待队列
用于暂存提交但尚未执行的任务。选择不同队列类型,直接影响线程池行为:
- SynchronousQueue:不存储任务,每个任务必须立刻由空闲线程处理,否则就触发扩容(适合高吞吐、低延迟场景);
- ArrayBlockingQueue:有界队列,容量固定,配合 maximumPoolSize 可控背压;
- LinkedBlockingQueue:默认无界(Integer.MAX_VALUE),容易掩盖问题(如生产者快于消费者导致 OOM);
- 慎用无界队列,尤其在任务执行时间不可控时。
threadFactory:线程创建工厂
用于定制新线程的名称、是否守护线程、优先级等。默认使用 Executors.defaultThreadFactory(),但线上建议自定义:
- 便于日志追踪(比如统一加前缀 “biz-pool-”);
- 避免线程名重复或默认命名混乱;
- 示例:new NamedThreadFactory("order-service")。
handler:拒绝策略
当线程数已达 maximumPoolSize 且队列已满时,新提交的任务将被拒绝。JDK 提供四种内置策略:
- AbortPolicy(默认):抛 RejectedExecutionException;
- CallerRunsPolicy:由提交任务的线程自己执行该任务(可缓解压力);
- DiscardPolicy:静默丢弃;
- DiscardOldestPolicy:丢弃队列头部任务,再尝试提交当前任务。
业务关键系统建议自定义 handler,记录日志或降级处理,而不是直接抛异常。
完整构造示例
一个典型、可控的线程池配置:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, // corePoolSize
8, // maximumPoolSize
60L, // keepAliveTime
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), // 有界队列
new NamedThreadFactory("async-task"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
这个配置意味着:常驻 4 个线程,最多扩到 8 个,空闲超 60 秒的非核心线程回收,任务积压最多 100 个,超限后由调用方自行执行任务。


















