java线程池有哪些拒绝策略

Java线程池内置4种拒绝策略:1. AbortPolicy默认抛异常;2. CallerRunsPolicy由调用方执行任务以降速;3. DiscardPolicy静默丢弃;4. DiscardOldestPolicy丢弃队列中最老任务。

Java线程池有4种内置拒绝策略,都实现在 `ThreadPoolExecutor` 类中,通过 `RejectedExecutionHandler` 接口定义。它们在任务无法被接纳(线程数已达最大、队列已满、线程池已关闭)时触发。

AbortPolicy(中止策略)

这是线程池的默认策略。当任务被拒绝时,直接抛出 RejectedExecutionException 异常。

适用场景:对任务失败敏感、需要立即感知并处理异常的系统,比如支付、订单创建等关键链路。

  • 不丢任务但会中断调用方流程
  • 必须配合 try-catch 或全局异常处理器使用,否则可能 crash
  • 适合强一致性、低容忍丢失的业务

CallerRunsPolicy(调用方运行策略)

由提交任务的线程(比如主线程、Web容器线程)自己执行该任务。

效果是“降速”:当线程池压力大时,调用方被拖慢,自然降低任务提交速率,避免雪崩。

  • 不会丢任务,也不抛异常
  • 可能阻塞调用线程,影响吞吐量和响应时间
  • 适合允许延迟、不能丢任务、并发量可控的后台服务

DiscardPolicy(丢弃策略)

静默丢弃新提交的任务,既不抛异常,也不做任何日志或通知。

风险高,容易掩盖问题,一般不建议直接使用。

  • 完全无感知,调试困难
  • 仅适用于日志采集、埋点上报等可丢失、非关键任务
  • 生产环境慎用,最好配合监控告警自定义实现

DiscardOldestPolicy(弃老策略)

丢弃队列中等待时间最长的那一个任务,再尝试把当前新任务加入队列。

本质是“用旧换新”,适合新任务时效性远高于旧任务的场景。

  • 仍可能丢任务,但优先保障最新请求
  • 要求队列是非公平的(如 LinkedBlockingQueue),否则可能丢错
  • 常见于实时消息推送、状态同步等对新鲜度敏感的业务
基本上就这些。四种策略覆盖了抛异常、降速、静默丢弃、替换丢弃等典型应对方式。实际项目中,更推荐基于 `RejectedExecutionHandler` 自定义策略——比如记录日志 + 上报 Prom

etheus + 触发熔断,让拒绝行为可观测、可追踪、可响应。