线程池的拒绝策略适用场景思考
ThreadPoolExecutor有四种拒绝策略。刚开始学习线程池的时候我就觉得,就是应该当任务饱和(达到拒绝策略)时,就应该拒绝任务,抛出异常。最近仔细思考了下,既然线程池这么设计,也应该有一定的道理。
默认的拒绝策略如下:AbortPolicy(丢弃任务并抛出 RejectedExecutionException 异常)
线程池的拒绝策略及使用场景
- AbortPolicy(默认策略)
行为:丢弃任务,并抛出RejectedExecutionException异常
适用场景:关键业务场景(如金融支付系统),需要通过异常快速知道系统过载 - CallerRunsPolicy
行为:由提交任务的线程(如主线程)直接执行被拒绝的任务。
适用场景:允许任务降级且对性能要求不高的场景(如日志记录),通过减缓提交速度防止线程池过载 - DiscardPolicy
行为:静默丢弃被拒绝的任务,不抛出异常
适用场景:非核心任务(如统计点击量),允许任务丢失且无需感知失败 - DiscardOldestPolicy
行为:丢弃任务中最旧的任务,重新提交新任务
适用场景:需要优先处理最新任务的场景(如实时消息推送),旧任务可以被覆盖
自定义拒绝策略
通过实现RejectExecutionHandler接口,可制定策略。比如写具体报错信息,写入数据库等操作。
Dubbo的线程池拒绝策略:记录详细日志、线程堆栈信息并抛出异常,便于问题排查