MST

星途 面试题库

面试题:Java中ThreadPoolExecutor拒绝策略在高并发场景下的优化与调优

在高并发场景下,系统使用ThreadPoolExecutor执行大量任务。现有四种拒绝策略都无法满足需求,因为既需要保证重要任务优先处理不被拒绝,又要对普通任务进行合理的拒绝处理。请设计一种综合解决方案,结合线程池参数调优、自定义拒绝策略以及任务优先级队列等技术手段,阐述详细的设计思路和实现步骤。
23.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 任务优先级队列:使用PriorityQueue来存储任务,使得任务按照优先级排序。这样在任务入队时,重要任务会排在队列前面,优先被执行。
  2. 自定义拒绝策略:继承RejectedExecutionHandler接口,实现自定义的拒绝策略。在拒绝策略中,区分重要任务和普通任务。对于重要任务,可以采取等待队列有空闲位置或者增加线程池容量等方式处理;对于普通任务,按照正常的拒绝逻辑处理。
  3. 线程池参数调优
    • 核心线程数:根据系统资源和预估的任务负载,设置一个合适的核心线程数,确保系统在正常负载下能够高效处理任务。
    • 最大线程数:设置合理的最大线程数,防止系统资源被过度消耗。同时要考虑系统的硬件资源,如CPU核数、内存大小等。
    • 队列容量:根据任务的类型和数量,设置合适的队列容量。如果队列容量过小,可能导致任务频繁被拒绝;如果队列容量过大,可能会占用过多内存。

实现步骤

  1. 定义任务优先级接口和任务类
// 定义任务优先级接口
public interface PrioritizedTask extends Comparable<PrioritizedTask> {
    int getPriority();
}

// 定义任务类,实现PrioritizedTask接口
public class CustomTask implements PrioritizedTask {
    private final int priority;
    private final Runnable task;

    public CustomTask(int priority, Runnable task) {
        this.priority = priority;
        this.task = task;
    }

    @Override
    public int getPriority() {
        return priority;
    }

    @Override
    public int compareTo(PrioritizedTask other) {
        return Integer.compare(other.getPriority(), this.getPriority());
    }

    public void run() {
        task.run();
    }
}
  1. 创建自定义拒绝策略
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
    private final ThreadPoolExecutor executor;

    public CustomRejectedExecutionHandler(ThreadPoolExecutor executor) {
        this.executor = executor;
    }

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (r instanceof CustomTask) {
            CustomTask task = (CustomTask) r;
            if (task.getPriority() == 1) { // 假设1为重要任务优先级
                // 等待队列有空闲位置
                while (executor.getQueue().size() >= executor.getQueue().capacity()) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
                executor.getQueue().offer(task);
            } else {
                // 普通任务,按照默认拒绝策略处理
                System.out.println("普通任务被拒绝: " + task);
            }
        }
    }
}
  1. 创建线程池并使用自定义拒绝策略和优先级队列
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        int corePoolSize = 5;
        int maximumPoolSize = 10;
        long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new PriorityBlockingQueue<>();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                new CustomRejectedExecutionHandler(executor));

        // 提交任务
        executor.submit(new CustomTask(1, () -> System.out.println("重要任务执行")));
        executor.submit(new CustomTask(2, () -> System.out.println("普通任务执行")));

        // 关闭线程池
        executor.shutdown();
    }
}

通过以上步骤,我们实现了在高并发场景下,既保证重要任务优先处理不被拒绝,又对普通任务进行合理的拒绝处理。同时,通过线程池参数调优,进一步优化系统性能。