callerrunspolicy 是 java 线程池提供的一种拒绝策略,其核心行为是在线程池无法接受新任务时,由提交任务的当前线程(即调用者)直接执行该任务。这种机制通过让调用者“亲自干活”来避免任务丢失,同时利用执行耗时自然地对任务提交速度进行限速,防止系统过载。

如何配置并使用 CallerRunsPolicy
要使用 CallerRunsPolicy,只需在创建 ThreadPoolExecutor 实例时将其作为第四个参数传入构造函数。当线程池处于关闭状态或队列已满且线程数达到上限时,线程池会触发此策略,此时主线程将阻塞并同步执行 Runnable 的 run() 方法,直到任务执行完毕才返回。

import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException {
// 核心线程2个,最大线程2个,队列容量1
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 2, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(1),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 提交3个任务:前2个由工作线程处理,第3个进入队列
for (int i = 0; i < 4; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " executing task " + taskId);
try { Thread.sleep(500); } catch (Exception e) {}
});
}
executor.shutdown();
}
}运行上述代码,预期输出中会出现名为 main 的线程执行某个任务的情况,这证实了调用者线程参与了任务执行。
立即学习“Java免费学习笔记(深入)”;
CallerRunsPolicy 与 AbortPolicy 的行为差异
对比默认的 AbortPolicy,CallerRunsPolicy 不会抛出异常中断程序,而是选择同步执行。在处理突发流量时,AbortPolicy 会导致任务被丢弃并引发 RejectedExecutionException,而 CallerRunsPolicy 则会让主线程变慢,从而间接降低后续任务的提交频率,起到一种背压(Backpressure)的作用。

import java.util.concurrent.*;
public class ComparePolicy {
public static void main(String[] args) {
// 测试 AbortPolicy
try {
ThreadPoolExecutor abortExec = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
new ThreadPoolExecutor.AbortPolicy()
);
abortExec.execute(() -> {});
abortExec.execute(() -> {}); // 触发拒绝
} catch (RejectedExecutionException e) {
System.out.println("AbortPolicy: Exception caught");
}
// 测试 CallerRunsPolicy
ThreadPoolExecutor callerExec = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
callerExec.execute(() -> {});
callerExec.execute(() -> {}); // 由主线程执行,无异常
System.out.println("CallerRunsPolicy: No exception");
}
}该对比程序的输出将显示 AbortPolicy 捕获到异常,而 CallerRunsPolicy 正常结束,证明后者具有容错性。
CallerRunsPolicy 在主线程执行时的具体表现
当 CallerRunsPolicy 生效时,主线程会同步执行任务。这意味着主线程会被阻塞,直到任务完成。如果任务是计算密集型的,主线程将被长时间占用;如果是 I/O 密集型,主线程也会等待 I/O 完成。这种行为适合用于需要保证任务不丢失且能容忍主线程延迟的场景。


















