java线程池拒绝策略是资源耗尽时的主动决策,仅在运行中、核心线程满、队列满、最大线程数达上限四条件同时满足时触发;abortpolicy抛异常需兜底,callerrunspolicy由调用线程执行实现反压,discardpolicy静默丢弃适合采样任务,discardoldestpolicy丢弃最老任务保新数据。

Java 线程池的拒绝策略(RejectedExecutionHandler)是任务无法被接纳时的最后一道控制逻辑,不是错误,而是资源耗尽时的主动决策。它只在线程池运行中、核心线程已满、工作队列已满、最大线程数已达上限这四个条件同时满足时才触发。
四种内置拒绝策略怎么用
它们都实现了 RejectedExecutionHandler 接口,使用时直接传入 ThreadPoolExecutor 构造函数即可:
-
AbortPolicy(默认策略):直接抛出
RejectedExecutionException。适合关键任务,如支付确认、库存扣减——失败必须被感知。
用法:new ThreadPoolExecutor.AbortPolicy()
注意:调用方必须try-catch,否则异常向上冒泡,可能中断业务或引发雪崩。 -
CallerRunsPolicy:由提交任务的线程(比如 Web 请求线程)同步执行该任务。不丢任务,天然反压。
用法:new ThreadPoolExecutor.CallerRunsPolicy()
适用场景:日志上报、异步通知等“不可丢但可延迟”的任务;慎用于高实时性接口,避免阻塞容器线程。 -
DiscardPolicy:静默丢弃新任务,不抛异常、不打日志、零开销。
用法:new ThreadPoolExecutor.DiscardPolicy()
仅建议用于埋点、心跳、采样类任务;生产环境需搭配监控看板,持续观察拒绝率是否异常升高。 -
DiscardOldestPolicy:尝试从队列头部移除最老任务,再重新提交当前任务。
用法:new ThreadPoolExecutor.DiscardOldestPolicy()
适合“保新弃旧”场景,如行情推送、消息轮询;要求队列支持poll()(如ArrayBlockingQueue、LinkedBlockingQueue)。
自定义拒绝策略怎么写
实现 RejectedExecutionHandler 接口,重写 rejectedExecution(Runnable r, ThreadPoolExecutor e) 方法。常见做法包括:
- 记录带上下文的日志(任务类名、线程池状态、队列大小、活跃线程数)
- 发送告警(如发 Slack、钉钉、企业微信)
- 落库或发 Kafka 做事后分析
- 抛出自定义异常(如
TaskRejectedException),让调用方明确感知并降级处理
示例(抛自定义异常):
public class CustomRejectHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
String msg = String.format("Task %s rejected. Pool: active=%d, queue=%d, poolSize=%d",
r, e.getActiveCount(), e.getQueue().size(), e.getPoolSize());
throw new TaskRejectedException(msg);
}
}
怎么配置到线程池
构造 ThreadPoolExecutor 时显式传入:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 4, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue(10),
new ThreadFactoryBuilder().setNameFormat("biz-%d").build(),
new CustomRejectHandler() // ← 这里替换为你选的策略
);
注意:execute() 和 submit() 都会触发拒绝策略;但 invokeAll()、invokeAny() 等批量方法内部也基于 execute(),同样生效。
容易忽略的关键点
- 拒绝策略只对 新提交的任务 生效,不影响已在执行或队列中等待的任务
- 线程池调用
shutdown()或shutdownNow()后,再提交任务也会触发拒绝策略 - 不要在自定义策略中做耗时操作(如远程调用、数据库写入),否则会卡住线程池的拒绝处理流程
- 测试拒绝策略要模拟真实饱和场景:小队列 + 少线程 + 快速提交,避免误判为“没触发”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











