核心目标
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
关键参数
-
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(默认):直接抛出
运行状态
核心状态共有 5 个:RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED。
-
RUNNING:接受新任务,处理队列任务。
-
SHUTDOWN(shutdown() 触发):不再接收新任务,但会执行队列中的任务,已有工作线程正常退出。
-
STOP(shutdownNow() 触发):不再接收任务,丢弃队列任务,中断正在运行的任务。尽力打断阻塞/等待状态,但不能强杀CPU密集循环或忽略中断的代码。
-
TIDYING:所有任务终止,线程数为 0,准备进入
TERMINATED。 -
TERMINATED:terminated() 执行完毕,彻底终止,生命周期闭合态。
状态迁移,只会向前
- RUNNING —(shutdown)→ SHUTDOWN —(清空且无 worker)→ TIDYING → TERMINATED
- RUNNING/SHUTDOWN —(shutdownNow)→ STOP —(无 worker)→ TIDYING → TERMINATED
线程状态
- NEW:新建状态,线程对象刚被创建,线程池通常看不到,线程池一旦创建线程就会
start()。 - RUNNABLE:线程正在执行任务,或者准备执行任务。
- BLOCKED:线程尝试获取一个对象锁(synchronized),但锁被其他线程占用。
- WAITING:无限期等待,直到被其他线程显式唤醒(
notify()/signal())。- 核心线程在等待任务时通常处于次状态。
- TIMED_WAITING:有时限的等待。
- 非核心线程会在此状态等待任务
- 如果核心线程设置了过期时间,也会在此状态等待任务
- TERMINATED:线程执行完毕,生命周期结束。在线程池中,非核心线程超时回收,或线程池关闭后,线程会进入
TERMINATED。
运行流程
简单使用
构建自定义线程池
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
ThreadFactory namedFactory = new ThreadFactory() {
private final AtomicInteger idx = new AtomicInteger(1);
@Override public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setName("biz-pool-" + idx.getAndIncrement());
t.setDaemon(false);
t.setUncaughtExceptionHandler((th, ex) ->
System.err.println("Uncaught in " + th.getName() + ": " + ex));
return t;
}
};
RejectedExecutionHandler reject = new ThreadPoolExecutor.CallerRunsPolicy(); // 退化到调用线程执行
ThreadPoolExecutor pool = new ThreadPoolExecutor(
4, // core
8, // max
60, TimeUnit.SECONDS, // keepAlive
new ArrayBlockingQueue<>(200), // 有界队列
namedFactory,
reject
);
pool.allowCoreThreadTimeOut(true); // 核心线程池也可回收
pool.prestartAllCoreThreads(); //预启动核心线程
使用 execut 与 submit 提交任务
// execute:仅提交
pool.execute(() -> 任务());
// submit:返回 Future,可拿结果/异常/取消
Future<Integer> future = pool.submit(() -> 任务());
try {
Integer v = future.get(2, TimeUnit.SECONDS); // 超时避免无限阻塞
System.out.println("result = " + v);
} catch (TimeoutException te) {
future.cancel(true); // 可中断取消
} catch (ExecutionException ee) {
// 任务内部异常在这里抛出,ee.getCause() 是真实异常
}
execute()- 没有返回值
- 只可以提交
Runnable任务 - 提交的任务如果抛出未检查异常,会直接抛出并可能导致线程终止
submit()- 会返回一个
Future对象 - 可以提交
Runnable或Callable类型的任务 - 提交的任务如果抛出异常,会被封装在
Future对象中,只有当调用Future.get()时才会抛出
- 会返回一个
使用 CompletableFuture 处理任务
创建异步任务
runAsync(Runnable runnable, Executor executor):无返回值supplyAsync(Supplier<U> supplier, Executor executor):有返回值
CompletableFuture.runAsync(() -> 任务());
CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> 任务());
完成后回调
thenAccept(Consumer<? super T> action):接收任务结果并消费(无返回值)thenApply(Function<? super T,? extends U> fn):接收任务结果并处理(有返回值,生成新的CompletableFuture)thenRun(Runnable action):任务完成后执行,不关心结果(无返回值)
CompletableFuture<String> supplyFuture = CompletableFuture.supplyAsync(() -> 任务());
// 1. 消费结果(无返回值)
supplyFuture.thenAccept(result -> System.out.println("消费结果:" + result));
// 2. 处理结果(有返回值)
CompletableFuture<Integer> applyFuture = supplyFuture.thenApply(result -> result.length());
System.out.println("处理后的结果:" + applyFuture.get());
// 3. 任务完成后执行(不关心结果)
supplyFuture.thenRun(() -> System.out.println("任务完成,执行后续操作"));
组合任务
-
thenCompose(Function<? super T, ? extends CompletionStage<U>> fn):串行执行CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> 任务1()); CompletableFuture<String> f2 = f1.thenCompose(result -> CompletableFuture.supplyAsync(() -> 任务2()) ); -
allOf(CompletableFuture<?>... cfs):等待所有任务完成CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3); all.thenRun(() -> { f1.join(); f2.join(); f3.join(); }); -
anyOf(CompletableFuture<?>... cfs):获取第一个完成的任务结果CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(300); } catch (InterruptedException e) {} return "f1"; }); CompletableFuture<String> taskB = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(200); } catch (InterruptedException e) {} return "f2"; }); // 取第一个完成的任务结果 CompletableFuture<Object> firstCompleted = CompletableFuture.anyOf(f1, f2); System.out.println(firstCompleted.get()); // 输出:来自f2的结果
异常处理
-
exceptionally(Function<Throwable, ? extends T> fn):任务异常时执行,返回默认值CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> { if (true) throw new RuntimeException("任务出错了"); return 100; }).exceptionally(ex -> { System.out.println("捕获异常:" + ex.getMessage()); return -1; // 异常时返回默认值 }); System.out.println(f1.get()); // 输出:-1 -
handle(BiFunction<? super T, Throwable, ? extends U> fn):无论成功或失败都执行,可处理结果或异常CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> 任务()) .handle((result, ex) -> { if (ex != null) { return "error"; } else { return result; } });
源码解读
AtomicInteger ctl: 主线程池控制状态,高位表示线程池运行状态,低位表示“工作线程数”。- runState「高 3 位」:表示线程池状态(如运行中、关闭中等)
- workerCount「低 29 位」:表示有效线程数
class Worker extends AbstractQueuedSynchronizer implements Runnable: 主要维护运行任务的线程的中断控制状态。继承 AQS,以简化每次任务执行时锁的获取与释放。这样做可以防止那些原本用于唤醒等待任务的工作线程的中断,反而错误地中断了正在运行任务的线程。
任务提交:execute(Runnable command)
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)
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)
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);
}
}