★ 线程池的核心参数与执行流程是怎样的?
结论先行:ThreadPoolExecutor 有七个核心参数:核心线程数、最大线程数、空闲存活时间、时间单位、阻塞队列、线程工厂、拒绝策略。执行铁律是:先占核心线程,核心满则排队进队列,队列满才扩到最大线程数,最大也满则触发拒绝策略——注意顺序是先排队、后扩线程,这与直觉相反,是高频考点。
七大参数
| 参数 | 含义 |
|---|---|
| corePoolSize | 核心线程数,常驻不回收(allowCoreThreadTimeOut 除外) |
| maximumPoolSize | 线程数上限 |
| keepAliveTime / unit | 非核心线程空闲存活时间 |
| workQueue | 任务等待队列(有界/无界) |
| threadFactory | 创建线程的工厂,建议自定义命名便于排查 |
| handler | 队列满且线程达上限时的拒绝策略 |
新任务提交流程
- 工作线程数 < corePoolSize → 直接新建核心线程执行任务。
- 工作线程数 ≥ corePoolSize → 任务放入 workQueue 排队等待。
- 队列已满且线程数 < maximumPoolSize → 新建非核心线程执行。
- 队列已满且线程数已达 maximumPoolSize → 交给 RejectedExecutionHandler。
import java.util.concurrent.*;
public class ThreadPoolDemo {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize
60, TimeUnit.SECONDS, // 非核心线程空闲 60s 回收
new ArrayBlockingQueue<>(10), // 有界队列
r -> new Thread(r, "biz-pool-" + r.hashCode()),
new ThreadPoolExecutor.AbortPolicy());
pool.execute(() -> System.out.println("task running"));
pool.shutdown(); // 不再接新任务,跑完存量后关闭
}
}
常见追问 / 记忆点
- 记忆点:一条口诀“核心 → 队列 → 扩容 → 拒绝”,扩线程永远排在排队之后。
- 追问:execute 提交的 Runnable 若抛异常,线程会退出并打印栈,最好在任务内部捕获处理。
- 追问:核心线程默认不回收;prestartAllCoreThreads() 可预热线程,避免首批请求因建线程变慢。