当线程池任务队列已满且线程数达最大值时,新任务被拒绝,可通过自定义rejectedexecutionhandler实现日志、降级等策略;java内置四种策略,但业务常需扩展;自定义handler需在构造threadpoolexecutor时传入,避免阻塞操作和无限重试。

当线程池任务队列已满且线程数达到最大值时,新提交的任务会被拒绝。此时可通过自定义 RejectedExecutionHandler 控制拒绝策略,而不是直接抛出 RejectedExecutionException。
理解拒绝时机与默认策略
拒绝发生在 execute() 调用时,前提是:
- 核心线程数已满
- 任务队列已满(如
ArrayBlockingQueue容量耗尽) - 非核心线程也已创建到
maximumPoolSize
Java 提供四种内置策略:AbortPolicy(抛异常)、CallerRunsPolicy(由提交线程执行)、DiscardPolicy(静默丢弃)、DiscardOldestPolicy(丢弃队首任务再重试)。但它们无法满足日志记录、降级、异步补偿等业务需求。
实现自定义 RejectedExecutionHandler
只需实现 RejectedExecutionHandler 接口,重写 rejectedExecution(Runnable r, ThreadPoolExecutor executor) 方法:
-
参数
r:被拒绝的原始任务(可能是FutureTask或普通Runnable) -
参数
executor:当前线程池实例,可用于获取状态(如getActiveCount()、getQueue().size()) - 方法内可做日志、落库、发消息、调用备用服务等,但避免阻塞或耗时操作,否则可能拖慢提交线程
示例:记录日志并尝试写入 Kafka 备份队列(非阻塞发送):
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
private final KafkaProducer
public LogAndRetryHandler(KafkaProducer
this.producer = producer;
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.warn("Task rejected: {}, pool: active={}, queue={}",
r.getClass().getSimpleName(),
executor.getActiveCount(),
executor.getQueue().size());
// 异步发送到 Kafka,不阻塞
producer.send(new ProducerRecord("rejected-tasks", r.toString()));
}
}
注册到线程池的正确方式
必须在构建线程池时传入自定义 handler,不能后期替换:
- 使用
ThreadPoolExecutor构造器时第 8 个参数传入实例 - 若用
Executors工具类(如newFixedThreadPool),其内部固定使用AbortPolicy,无法更换 —— 所以务必手动构造ThreadPoolExecutor - Spring 中可通过
@Bean定义线程池,并注入自定义 handler
关键代码片段:
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
keepAliveTime, TimeUnit.SECONDS,
new ArrayBlockingQueue(queueCapacity),
new CustomThreadFactory(),
new LogAndRetryHandler(kafkaProducer)
);
注意事项与常见陷阱
自定义 handler 看似简单,但容易踩坑:
- 不要在 handler 中调用
executor.execute(r)重试 —— 可能再次触发拒绝,造成无限递归或栈溢出 - 避免同步 I/O(如写文件、远程 HTTP 调用),推荐异步、缓冲、带超时的轻量操作
- 若任务本身携带上下文(如用户 ID、TraceID),应在 handler 中提取并记录,便于问题追踪
- 测试时需模拟满负荷场景(如快速提交超量任务),验证 handler 是否按预期触发
不复杂但容易忽略细节。关键是把拒绝当成可观测事件来设计,而非错误兜底。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










