特点:当任务无法被线程池执行时,线程池会丢弃队列中最旧的未处理任务,然后尝试重新提交当前任务。


使用场景:适用于对新任务优先级较高的场景,当线程池无法接受新任务时,会丢弃一些等待时间较长的旧任务,以便接受新任务。


示例代码:


import java.util.concurrent.*;


public class DiscardOldestPolicyDemo {

   public static void main(String[] args) {

       ThreadPoolExecutor executor = new ThreadPoolExecutor(

               2, 2, 0L, TimeUnit.MILLISECONDS,

               new LinkedBlockingQueue<>(2),

               new ThreadPoolExecutor.DiscardOldestPolicy());


       for (int i = 0; i < 5; i++) {

           final int taskId = i;

           executor.submit(() -> {

               System.out.println("Executing task " + taskId + " by " + Thread.currentThread().getName());

               try {

                   Thread.sleep(1000);

               } catch (InterruptedException e) {

                   Thread.currentThread().interrupt();

               }

           });

       }


       executor.shutdown();

       // 等待所有任务完成(尽管有些任务可能已被丢弃)

       try {

           if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {

               executor.shutdownNow();

           }

       } catch (InterruptedException e) {

           executor.shutdownNow();

           Thread.currentThread().interrupt();

       }

   }

}


在这个例子中,我们尝试提交了5个任务到一个容量为2的线程池,其中任务队列的最大容量也设置为2。由于DiscardOldestPolicy被用作拒绝策略,当尝试提交第5个任务时,队列中最旧的任务(即第1个任务)将被丢弃,然后尝试重新提交当前任务(但在这个例子中,由于线程池和队列都已满,第5个任务实际上也会被丢弃,因为没有额外的空间来容纳它)。


5. 自定义拒绝策略

除了上述四种内置的拒绝策略外,ThreadPoolExecutor还允许你通过实现RejectedExecutionHandler接口来定义自己的拒绝策略。这提供了极高的灵活性,可以根据具体需求定制拒绝任务的行为。


自定义拒绝策略示例:


import java.util.concurrent.*;


public class CustomRejectionPolicy implements RejectedExecutionHandler {

   @Override

   public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

       // 在这里定义你的自定义处理逻辑

       System.out.println("Task " + r.toString() + " was rejected");

       // 可以选择记录日志、抛出异常、使用备用线程池执行等

   }


   public static void main(String[] args) {

       ThreadPoolExecutor executor = new ThreadPoolExecutor(

               2, 2, 0L, TimeUnit.MILLISECONDS,

               new LinkedBlockingQueue<>(2),

               new CustomRejectionPolicy());


       // 提交任务...

   }

}


在自定义拒绝策略中,你可以访问被拒绝的任务(Runnable r)和线程池实例(ThreadPoolExecutor executor),从而可以根据这些信息来做出决策,比如记录日志、抛出异常、将任务提交到另一个线程池等。


线程池拒绝策略是处理超出线程池处理能力的任务的一种方式。Java提供了四种内置的拒绝策略,每种策略都有其适用场景。然而,在复杂的应用场景中,这些内置策略可能无法满足需求,此时可以通过实现自定义拒绝策略来灵活处理。无论是使用内置策略还是自定义策略,都需要根据应用的具体需求和资源状况来合理选择,以确保系统的稳定性和高效性。


在设计系统时,合理配置线程池的大小、任务队列的容量以及选择合适的拒绝策略,对于提高系统的并发处理能力和稳定性至关重要。