Java线程池高频面试题(含实战代码与源码解析)
一、线程池核心参数(必考)
核心参数定义
线程池的核心逻辑封装在 ThreadPoolExecutor 中,其构造函数的7个参数决定了线程池的行为特性:
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数(常驻线程,空闲时不销毁)
int maximumPoolSize, // 最大线程数(核心+非核心线程的峰值)
long keepAliveTime, // 非核心线程空闲存活时间
TimeUnit unit, // 存活时间单位(如秒、毫秒)
BlockingQueue<Runnable> workQueue, // 任务队列(缓存待执行任务)
ThreadFactory threadFactory, // 线程工厂(定制线程名称、优先级等)
RejectedExecutionHandler handler // 拒绝策略(任务满时的处理方式)
)
关键参数深度解析
1. 核心线程数 vs 最大线程数
- corePoolSize:线程池的“基础兵力”,即使空闲也会保留(除非设置
allowCoreThreadTimeOut=true)。 - maximumPoolSize:线程池的“峰值兵力”,仅当队列满时才会创建非核心线程,任务完成后非核心线程会在
keepAliveTime后销毁。
示例场景:corePoolSize=2,maximumPoolSize=5,workQueue=容量10
- 提交2个任务:核心线程直接执行;
- 提交第3~12个任务:进入队列等待;
- 提交第13个任务:创建第3个非核心线程;
- 提交第16个任务:线程数达5,触发拒绝策略。
2. 任务队列类型(性能与安全关键)
| 队列类型 | 特点 | 适用场景 | 风险点 |
|---|---|---|---|
ArrayBlockingQueue |
有界队列,需指定容量 | 核心业务,控制任务积压上限 | 容量过小易触发拒绝策略 |
LinkedBlockingQueue |
无界队列(默认Integer.MAX_VALUE) |
非核心任务,允许临时积压 | 任务过多导致内存溢出(OOM) |
SynchronousQueue |
不存储任务,直接提交给线程 | 任务执行快,需即时响应 | 线程数不足时立即触发拒绝策略 |
3. 线程工厂与拒绝策略
- 线程工厂:默认使用
Executors.defaultThreadFactory(),建议自定义以规范线程名称(如task-pool-1-thread-1),便于问题排查。 - 拒绝策略:详见第三章。
二、线程池工作流程(核心执行逻辑)
四步执行规则
线程池处理任务的流程严格遵循以下顺序(源码对应 ThreadPoolExecutor#execute 方法):
- 核心线程未满:创建核心线程执行任务;
- 核心线程已满:任务放入工作队列等待;
- 队列已满:创建非核心线程执行任务;
- 线程数达最大值:触发拒绝策略。
源码核心逻辑片段
public void execute(Runnable command) {
if (command == null) throw new NullPointerException();
int c = ctl.get();
// 1. 核心线程未满,创建核心线程
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true)) return;
c = ctl.get();
}
// 2. 核心线程满,尝试入队
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (!isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 3. 队列满,尝试创建非核心线程
else if (!addWorker(command, false))
// 4. 线程数达最大值,触发拒绝策略
reject(command);
}
代码案例:模拟工作流程
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolFlowDemo {
public static void main(String[] args) {
// 配置:核心2,最大5,队列容量3,拒绝策略为CallerRunsPolicy
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
r -> new Thread(r, "demo-pool-thread-"), // 自定义线程工厂
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 提交6个任务(核心2 + 队列3 = 5,第6个触发扩容非核心线程)
for (int i = 1; i <= 6; i++) {
int taskId = i;
executor.execute(() -> {
System.out.printf("线程[%s]执行任务%d%n",
Thread.currentThread().getName(), taskId);
try {
Thread.sleep(100); } catch (InterruptedException e) {
}
});
System.out.printf("提交任务%d后,线程数:%d,队列大小:%d%n",
taskId, executor.getPoolSize(), executor.getQueue

最低0.47元/天 解锁文章
1181

被折叠的 条评论
为什么被折叠?



