线程池执行任务的过程是一个多阶段协作的精密流程,涉及任务调度、线程管理、资源分配等核心机制。下面通过底层源码解析和流程图解,详细说明其工作原理:
一、线程池执行任务全流程(7个关键步骤)
二、分步骤深度解析
1. 任务提交(execute方法)
// ThreadPoolExecutor.execute() 源码核心逻辑
public void execute(Runnable command) {
if (command == null) throw new NullPointerException();
int c = ctl.get(); // 获取控制状态(包含线程数+运行状态)
// 步骤1:核心线程未满 → 创建Worker
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true)) // 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:队列满且线程未达max → 创建非核心线程
else if (!addWorker(command, false))
reject(command); // 步骤4:触发拒绝策略
}
2. Worker线程创建(addWorker)
private boolean addWorker(Runnable firstTask, boolean core) {
// 检查线程数是否超限(core决定检查corePoolSize还是maxPoolSize)
if (workerCount >= (core ? corePoolSize : maximumPoolSize))
return false;
// 创建Worker对象(封装任务和线程)
Worker w = new Worker(firstTask);
Thread t = w.thread;
// 将Worker加入HashSet<Worker> workers
workers.add(w);
// 启动线程(最终调用Worker.run())
t.start();
return true;
}
3. Worker执行逻辑(核心循环)
// Worker.run() → runWorker() 源码精简版
final void runWorker(Worker w) {
Runnable task = w.firstTask;
w.firstTask = null;
while (task != null || (task = getTask()) != null) {
try {
task.run(); // 执行任务
} finally {
task = null; // 清空引用
}
}
processWorkerExit(w); // 线程回收
}
// 从队列获取任务(支持超时控制)
private Runnable getTask() {
boolean timed = allowCoreThreadTimeOut || workerCount > corePoolSize;
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
return r;
}
三、关键机制详解
1. 线程复用机制
- while循环+任务队列:Worker线程不会执行完任务就终止,而是通过
getTask()从队列获取新任务 - 阻塞/超时控制:
- 核心线程:默认调用
queue.take()永久阻塞 - 非核心线程:使用
queue.poll(keepAliveTime)超时等待
2. 任务调度优先级
执行顺序遵循以下严格优先级:
- 核心线程(如果未满)
- 任务队列(如果未满)
- 非核心线程(如果未达max)
- 拒绝策略(如果队列和线程全满)
3. 线程回收流程
graph LR
A[getTask()返回null] --> B[减少Worker计数]
B --> C[从workers集合移除]
C --> D[尝试终止线程池]
四、不同队列策略的影响
| 队列类型 | 行为特点 | 适用场景 |
|---|---|---|
SynchronousQueue | 直接传递任务,不存储 | 高吞吐快速存储 |
LinkedBlockingQueue | 无界/有界FIFO队列 | 需要缓冲的任务池(FixedThreadPool) |
ArrayBlockingQueue | 有界FIFO队列 | 控制资源消耗 |
PriorityBlockingQueue | 按优先级排序 | 任务有优先级差异 |
五、异常处理机制
- 任务异常:被Worker捕获后不影响线程继续运行
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} finally {
afterExecute(task, thrown); // 可重写该方法处理异常
}
- 线程终止:异常导致线程退出时,会创建新Worker补充
六、生产环境问题诊断
1. 线程池卡死排查
# 使用jstack查看线程状态
jstack <pid> | grep -A 10 <thread_pool_name>
# 典型问题:
# - WAITING on java.util.concurrent.FutureTask@1a2b3c (常见于未设置超时)
# - BLOCKED on lock (线程间死锁)
2. 性能调优参数
// 动态调整线程池参数(需自定义ThreadPoolExecutor)
executor.setCorePoolSize(newSize);
executor.setMaximumPoolSize(newMaxSize);
executor.setRejectedExecutionHandler(newPolicy);
七、完整执行流程图解
理解线程池的任务执行流程,是编写高性能并发程序的基础。建议结合jstack和监控工具实时观察线程池状态,根据业务特点合理配置参数。
2万+

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



