java线程池的rejectedexecutionhandler仅在饱和(maxpoolsize+队列满)或关闭时触发,需配合有界队列和合理参数才生效;内置四种策略各适配不同场景,自定义策略应抛出含上下文的异常并避免调用父类方法。

Java 线程池通过 RejectedExecutionHandler 接口统一处理任务拒绝逻辑,它只在“线程池饱和”或“已关闭”两种明确场景下被触发——即:当前线程数已达 maximumPoolSize 且工作队列已满,或线程池已调用 shutdown()/shutdownNow()。不是所有提交失败都会走这里,只有经过“尝试新建核心线程→入队→尝试扩容至最大线程数”三级流程后仍无法接纳任务时,才会交由该处理器执行。
四种内置拒绝策略的行为与适用点
它们都实现了 RejectedExecutionHandler 接口,可直接传入 ThreadPoolExecutor 构造函数:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
AbortPolicy(默认):抛出
RejectedExecutionException,适合需要快速感知过载、配合监控告警的场景;调用方必须显式捕获处理,否则中断主流程。 - CallerRunsPolicy:由提交任务的线程(如 Web 请求线程)同步执行该任务,起到反压降速作用;适用于不能丢任务的关键业务,但要注意避免主线程长时间阻塞影响响应。
- DiscardPolicy:静默丢弃,不抛异常也不记录;适合日志、埋点等可丢失的非关键任务,但需配套监控防止无感雪崩。
- DiscardOldestPolicy:丢弃队列头部最老任务,再尝试重新提交当前任务;适合只关心最新数据的场景(如实时行情更新),但可能误删重要历史任务。
自定义拒绝策略的正确写法
要抛出自定义异常(如 TaskRejectedException),不能仅替换异常类型,而必须实现接口并主动 throw:
- 定义继承
RuntimeException的异常类,支持携带上下文(任务、队列大小、活跃线程数等); - 实现
RejectedExecutionHandler,在rejectedExecution方法中构造并抛出该异常; - 注意:不要调用
super.rejectedExecution(),否则仍会触发默认行为; - 该异常会原样抛给调用
execute()或submit()的线程,由上层决定降级逻辑(如返回兜底数据、写入延迟队列等)。
策略生效的前提条件
拒绝策略不是“一提交就触发”,它的执行依赖线程池参数配置是否合理:
- 使用有界队列(如
ArrayBlockingQueue),而非LinkedBlockingQueue无界队列——否则队列永远不会满,永远扩不到最大线程数,也就不会触发拒绝; -
corePoolSize和maximumPoolSize需根据业务类型设置:CPU 密集型建议设为 CPU 核心数 + 1,IO 密集型可适当放大; - 务必搭配命名线程工厂(
ThreadFactory),便于排查时通过线程名定位具体线程池实例; - 生产环境建议用自定义策略,至少记录日志 + 上报监控指标(如 Prometheus counter),避免沉默失败。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










