MST

星途 面试题库

面试题:Java中ThreadPoolExecutor的拒绝策略及应用场景

请列举ThreadPoolExecutor的四种内置拒绝策略,并阐述每种拒绝策略在实际应用中的适用场景,以及如何自定义拒绝策略。
30.8万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. AbortPolicy(默认拒绝策略)
    • 策略描述:直接抛出 RejectedExecutionException 异常。
    • 适用场景:适用于希望在任务被拒绝时立即知晓并处理异常情况的场景,比如关键业务流程,不允许任务丢失,一旦任务无法执行就需要马上处理。
  2. CallerRunsPolicy
    • 策略描述:当任务被拒绝添加时,会在调用 execute 方法的线程中直接执行被拒绝的任务。
    • 适用场景:适用于对性能要求不是特别高,但是希望能尽量处理提交任务的场景,它会降低新任务的提交速度,缓解线程池的压力。
  3. DiscardPolicy
    • 策略描述:直接丢弃被拒绝的任务,不做任何处理。
    • 适用场景:适用于那些对任务执行结果不关心,允许任务丢失的场景,比如一些日志记录任务,丢失几条记录对整体业务影响不大。
  4. DiscardOldestPolicy
    • 策略描述:丢弃队列中等待时间最长的任务,然后尝试将新任务添加到队列中。
    • 适用场景:适用于处理优先级较高的任务场景,优先保证新提交的高优先级任务能被处理,而将等待时间过长的低优先级任务丢弃。

自定义拒绝策略

  1. 实现 RejectedExecutionHandler 接口,重写 rejectedExecution 方法。示例代码如下:
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 自定义处理逻辑,例如记录日志、将任务保存到其他地方等
        System.out.println("Task " + r.toString() + " rejected from " + executor.toString());
    }
}
  1. 在创建 ThreadPoolExecutor 时,将自定义的拒绝策略实例作为参数传入。示例代码如下:
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CustomRejectionPolicyExample {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 
                4, 
                10, 
                TimeUnit.SECONDS, 
                new LinkedBlockingQueue<>(2), 
                new CustomRejectedExecutionHandler());
        for (int i = 0; i < 10; i++) {
            executor.execute(new Task("Task-" + i));
        }
        executor.shutdown();
    }
}

class Task implements Runnable {
    private String name;
    public Task(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " is processing " + name);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

上述代码展示了如何自定义拒绝策略并在 ThreadPoolExecutor 中使用。在 CustomRejectedExecutionHandler 类中实现了自定义的拒绝处理逻辑,在 CustomRejectionPolicyExample 类中创建了 ThreadPoolExecutor 并使用自定义拒绝策略。