MST

星途 面试题库

面试题:Java线程池中如何通过设置合适的拒绝策略来提升可管理性

在Java线程池中,当任务提交时线程池已饱和,有几种常见的拒绝策略?请分别阐述每种拒绝策略的作用及适用场景,并举例说明如何在代码中设置这些拒绝策略。
40.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. AbortPolicy(默认策略)
    • 作用:当任务无法被执行时,直接抛出RejectedExecutionException异常。
    • 适用场景:适用于需要立即反馈任务执行失败信息的场景,比如在一些对任务执行成功率要求极高,不允许任务默默丢弃的场景。
    • 代码示例
import java.util.concurrent.*;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                2,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < 4; i++) {
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " is running");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }
}
  1. CallerRunsPolicy
    • 作用:当任务无法被执行时,该任务将由提交任务的线程来执行。这样做可以减少新任务的提交速度,给线程池一些时间来处理任务。
    • 适用场景:适用于对任务处理实时性要求不是特别高,并且提交任务的线程有能力处理任务的场景。比如在一些轻量级的应用中,主线程有空闲时间来处理额外任务。
    • 代码示例
import java.util.concurrent.*;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                2,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 4; i++) {
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " is running");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }
}
  1. DiscardPolicy
    • 作用:当任务无法被执行时,直接丢弃该任务,不做任何处理。
    • 适用场景:适用于那些对任务执行结果不是特别关注,允许任务丢失的场景。比如在一些日志记录任务等,偶尔丢失一两条日志记录对整体业务影响不大。
    • 代码示例
import java.util.concurrent.*;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                2,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.DiscardPolicy());
        for (int i = 0; i < 4; i++) {
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " is running");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }
}
  1. DiscardOldestPolicy
    • 作用:当任务无法被执行时,会丢弃阻塞队列中等待时间最长的任务,然后尝试提交当前任务。
    • 适用场景:适用于希望优先处理最新提交的任务,对旧任务的处理优先级较低的场景。比如在一些实时数据处理场景中,更关注最新的数据。
    • 代码示例
import java.util.concurrent.*;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                2,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        for (int i = 0; i < 4; i++) {
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " is running");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }
}