MST

星途 面试题库

面试题:Java线程池拒绝策略如何自定义及应用场景

假设你正在开发一个高并发的系统,现有的Java线程池默认拒绝策略无法满足业务需求。请阐述如何自定义一个线程池拒绝策略,并举例说明在何种业务场景下,该自定义拒绝策略会比默认策略更适用。
17.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

自定义线程池拒绝策略步骤

  1. 实现RejectedExecutionHandler接口,该接口只有一个方法rejectedExecution(Runnable r, ThreadPoolExecutor executor)
  2. 在实现类中编写自定义的拒绝逻辑。例如,可以记录被拒绝任务的相关信息,尝试重新提交任务,或者根据业务需求采取其他处理方式。

示例代码

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("任务 " + r.toString() + " 被拒绝,线程池状态:" + executor.toString());
        // 这里可以添加自定义处理逻辑,如记录日志、尝试重新提交任务等
    }
}

使用自定义拒绝策略

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Main {
    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.submit(() -> {
                try {
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName() + " 执行任务");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }
}

适用业务场景

  1. 日志记录场景:在日志收集系统中,当线程池饱和无法处理新的日志记录任务时,默认策略可能直接丢弃任务。而自定义拒绝策略可以将被拒绝的日志任务记录到文件或者其他持久化存储中,保证日志不丢失,便于后续分析。
  2. 重试场景:在一些订单处理系统中,如果由于系统瞬时负载过高,订单处理任务被线程池拒绝,自定义拒绝策略可以尝试将任务重新提交到线程池,或者发送到一个延迟队列稍后处理,以确保订单最终能够被处理,而不是像默认策略那样直接丢弃任务导致订单处理失败。