MST

星途 面试题库

面试题:Java BIO线程池优化中的队列处理

在Java BIO线程池优化场景下,当任务提交速度超过线程池处理速度时,任务会进入队列等待处理。现有一个使用LinkedBlockingQueue的线程池,如何确保在队列满时采取合理的拒绝策略,以避免系统出现异常或性能瓶颈?请给出具体的代码示例。
35.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 定义线程池并设置拒绝策略: 在创建ThreadPoolExecutor时,可以通过构造函数的参数设置拒绝策略。Java提供了几种内置的拒绝策略,如AbortPolicy(默认,队列满且线程池饱和时抛出RejectedExecutionException)、CallerRunsPolicy(将任务回退到调用者线程执行)、DiscardPolicy(直接丢弃任务)、DiscardOldestPolicy(丢弃队列中最老的任务,然后尝试提交当前任务)。

以下是使用CallerRunsPolicy拒绝策略的示例代码:

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

public class ThreadPoolWithRejectionPolicy {
    public static void main(String[] args) {
        // 定义线程池核心线程数
        int corePoolSize = 5;
        // 定义线程池最大线程数
        int maximumPoolSize = 10;
        // 线程存活时间
        long keepAliveTime = 10;
        // 存活时间单位
        TimeUnit unit = TimeUnit.SECONDS;
        // 使用LinkedBlockingQueue作为任务队列
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(5);
        // 创建线程池并设置CallerRunsPolicy拒绝策略
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                new ThreadPoolExecutor.CallerRunsPolicy());

        // 模拟提交任务
        for (int i = 0; i < 20; i++) {
            int taskNumber = i;
            executor.submit(() -> {
                System.out.println("Task " + taskNumber + " is being processed by " + Thread.currentThread().getName());
                try {
                    // 模拟任务执行时间
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

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

在上述代码中:

  • 首先创建了一个LinkedBlockingQueue作为任务队列,容量为5。
  • 然后通过ThreadPoolExecutor的构造函数创建线程池,核心线程数为5,最大线程数为10,线程存活时间为10秒。
  • 最后设置拒绝策略为CallerRunsPolicy,当队列满且线程池饱和时,任务将由调用者线程执行。

如果想使用其他拒绝策略,例如DiscardPolicy,只需将new ThreadPoolExecutor.CallerRunsPolicy()替换为new ThreadPoolExecutor.DiscardPolicy()即可。同样,AbortPolicyDiscardOldestPolicy也可以类似替换。