线程池的拒绝策略有哪些?

在 Java 中,线程池的拒绝策略(RejectedExecutionHandler)用于处理当线程池无法接受新任务的情况(例如:线程池已关闭,或线程池、任务队列均达到容量上限)。Java 线程池(ThreadPoolExecutor)提供了以下四种内置拒绝策略:

AbortPolicy(默认策略)

  • 行为:直接抛出 RejectedExecutionException 异常,拒绝新任务。
  • 适用场景:需要严格保证任务不被丢失的场景,开发者可以显式捕获异常并处理。

CallerRunsPolicy

  • 行为:由提交任务的线程(调用者线程)直接执行该任务,而非交给线程池。
  • 适用场景:希望降低任务提交速度,避免主线程提交任务过快导致系统过载(例如实现“负反馈”机制)。

DiscardPolicy

  • 行为:直接静默丢弃新任务,不抛出异常也不执行任务。
  • 适用场景:允许任务丢失的场景(如日志清理、不关键的后台任务)。

DiscardOldestPolicy

  • 行为:丢弃任务队列中最旧的未处理任务(即队列头部的任务),然后尝试重新提交当前任务。
  • 适用场景:允许丢弃旧任务以优先处理新任务(如实时性要求较高的场景)。
  • 注意:可能丢失重要任务,需谨慎使用。

自定义拒绝策略

除了内置策略,可以通过实现 RejectedExecutionHandler 接口自定义拒绝逻辑。

 public class CustomRejectionPolicy implements RejectedExecutionHandler {
     @Override
     public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
         // 自定义逻辑(如记录日志、暂存任务、重试等)
         System.out.println("Task rejected: " + r);
     }
 }

如何设置拒绝策略?

在创建线程池时指定:

 ThreadPoolExecutor executor = new ThreadPoolExecutor(
     corePoolSize, // 核心线程数
     maxPoolSize,  // 最大线程数
     keepAliveTime,
     TimeUnit.SECONDS,
     new LinkedBlockingQueue<>(100), // 任务队列
     new CustomRejectionPolicy()      // 自定义拒绝策略
 );