核心目标
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
关键参数
-
corePoolSize (核心线程数):线程池中始终保持的线程数量,即使这些线程处于空闲状态(未执行任务),除非设置了
allowCoreThreadTimeOut
(允许核心线程超时)参数。 -
maximumPoolSize (最大线程数):线程池允许创建的最大线程数量,是线程池能容纳的线程上限。
-
keepAliveTime + unit (空闲线程存活时间 + 时间单位):非核心线程空闲多久被回收;开启
allowCoreThreadTimeOut(true)
后核心也会回收。 -
workQueue (任务队列):用于在任务执行前暂存任务的队列,该队列仅存放通过
execute()
方法提交的Runnable
类型任务,决定"排队 vs 扩容"的策略。-
SynchronousQueue:同步队列,不存储,直接移交。
-
LinkedBlockingQueue(默认无界):"先排队,后扩容";风险是无界等待,吞吐高、延迟可变。
-
ArrayBlockingQueue(有界):常用于生产,配合 maximumPoolSize 和拒绝策略。
-
PriorityBlockingQueue:按优先级执行任务。
-
-
threadFactory (线程工厂):线程池创建新线程时所使用的 "工厂类",用于统一定义线程的名称、优先级、是否为守护线程(daemon thread)等属性。
-
handler (拒绝策略):当线程池的线程数已达到
maximumPoolSize
(最大线程数),且任务队列(workQueue
)也已装满时,新提交的任务会被 "拒绝",此时将由该处理器定义拒绝任务的处理方式。- AbortPolicy(默认):直接抛出
RejectedExecutionException
异常,中断任务提交; - CallerRunsPolicy:由提交任务的 "调用线程"(如主线程)自行执行该任务,减缓任务提交速度;
- DiscardPolicy:默默丢弃新任务,不抛出异常也不处理;
- DiscardOldestPolicy:丢弃任务队列中 "最旧" 的未处理任务,然后尝试提交新任务。
- AbortPolicy(默认):直接抛出
源码解读
AtomicInteger ctl
: 主线程池控制状态,高位表示线程池运行状态,低位表示"工作线程数"。- runState「高 3 位」:表示线程池状态(如运行中、关闭中等)
- workerCount「低 29 位」:表示有效线程数
class Worker extends AbstractQueuedSynchronizer implements Runnable
: 主要维护运行任务的线程的中断控制状态。继承 AQS,以简化每次任务执行时锁的获取与释放。这样做可以防止那些原本用于唤醒等待任务的工作线程的中断,反而错误地中断了正在运行任务的线程。
任务提交:execute(Runnable command)
java
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
// 如果运行的线程数少于 corePoolSize,就尝试启动一个新线程,并将给定的任务作为它的第一个任务。
// 调用 addWorker 会以原子方式检查 runState 和 workerCount,从而避免错误地增加线程(在不该增加时),通过返回 false 来阻止。
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
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);
}
// 如果任务无法入队,那么就尝试增加一个新线程。如果失败了,就可以确定线程池已经关闭或已饱和,因此拒绝该任务。
else if (!addWorker(command, false))
reject(command);
}
新增工作线程:addWorker(Runnable firstTask, boolean core)
java
private boolean addWorker(Runnable firstTask, boolean core) {
// 阶段一:状态/容量快速判断 + CAS 增量(外层 retry + 内层自旋)
retry:
for (int c = ctl.get();;) {
// Check if queue empty only if necessary.
if (runStateAtLeast(c, SHUTDOWN)
&& (runStateAtLeast(c, STOP)
|| firstTask != null
|| workQueue.isEmpty()))
return false;
for (;;) {
// 判断工作线程,是否大于核心线程数或者最大线程数
if (workerCountOf(c)
>= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
return false;
// CAS 增加 workerCount,成功跳出两层循环,失败重新获取状态,失败原因是SHUTDOWN还是计数竞争
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateAtLeast(c, SHUTDOWN))
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
// 阶段二:构造 Worker 并在互斥下注册
try {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
// 加锁
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int c = ctl.get();
// 仍然是 Running 状态,或者 STOP,没有新任务(清空队列,补线程)
if (isRunning(c) ||
(runStateLessThan(c, STOP) && firstTask == null)) {
// 防止重复启动
if (t.getState() != Thread.State.NEW)
throw new IllegalThreadStateException();
// worker 添加,更新最大线程数
workers.add(w);
workerAdded = true;
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
// 如果未启动成功,失败处理
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
线程主循环:runWorker(Worker w)
java
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
// 可能一开始就带有一个初始任务,此时不需要再去获取第一个任务。否则,只要线程池处于运行状态,就会通过 getTask 获取任务。
while (task != null || (task = getTask()) != null) {
w.lock();
// 在运行任何任务之前,会先获取锁,以防止线程在任务执行期间被其他线程池中断。然后会确保只要线程池没有停止,当前线程就不会被设置为中断状态。
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
try {
// 运行任务
task.run();
afterExecute(task, null);
} catch (Throwable ex) {
afterExecute(task, ex);
throw ex;
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}