Java线程池的拒绝策略有哪些种类?
Java 线程池有四种内置的拒绝策略,用来处理当任务太多,无法继续接受时的情况。每种策略的处理方式不同,帮助程序更灵活地应对任务积压。
这四种拒绝策略是:
AbortPolicy(抛异常):如果线程池无法接受新的任务,它会抛出一个错误,告诉你任务没有被处理。
CallerRunsPolicy(调用者执行):如果线程池满了,它会把任务交给发起任务的“调用者”来处理,而不是丢弃任务或报错。
DiscardOldestPolicy(丢弃最旧任务):线程池会丢弃掉队列里最早的任务,然后把新的任务加进来。就像是做队列管理,丢掉排在最前面的任务。
DiscardPolicy(直接丢弃):如果线程池满了,新的任务就会被直接丢弃,不做任何处理。
自定义拒绝策略:
如果这些内置的策略不符合你的需求,你还可以自己定义拒绝策略,来根据特定需求灵活处理任务。
总之,这些拒绝策略让你能够根据不同情况做出合适的反应,避免任务过多时程序崩溃或者不做处理。
🧠 知识内容
1️⃣ AbortPolicy(默认策略)
特点:直接抛出 RejectedExecutionException 异常。
适用场景:必须明确通知调用者任务未被执行的场景。
ExecutorService executor = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1),
new ThreadPoolExecutor.AbortPolicy());
executor.submit(() -> System.out.println(“任务1”));
executor.submit(() -> System.out.println(“任务2”));
executor.submit(() -> System.out.println(“任务3”)); // 🚨 抛出 RejectedExecutionException
2️⃣ CallerRunsPolicy
特点:当线程池忙时,新任务由提交任务的线程直接执行。
适用场景:需要通过减缓任务提交速度来稳定系统。
ExecutorService executor = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1),
new ThreadPoolExecutor.CallerRunsPolicy());
executor.submit(() -> System.out.println(“任务1”));
executor.submit(() -> System.out.println(“任务2”));
executor.submit(() -> System.out.println(“任务3”)); // 🏃 由主线程执行
3️⃣ DiscardOldestPolicy
特点:丢弃队列中最早的任务,然后尝试提交新任务。
适用场景:需要优先保证新任务被执行。
ExecutorService executor = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1),
new ThreadPoolExecutor.DiscardOldestPolicy());
executor.submit(() -> System.out.println(“任务1”));
executor.submit(() -> System.out.println(“任务2”));
executor.submit(() -> System.out.println(“任务3”)); // 🗑 丢弃任务1,执行任务3
4️⃣ DiscardPolicy
特点:直接丢弃新提交的任务,无任何提示或处理。
适用场景:允许任务丢弃,不需要通知或处理。
ExecutorService executor = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1),
new ThreadPoolExecutor.DiscardPolicy());
executor.submit(() -> System.out.println(“任务1”));
executor.submit(() -> System.out.println(“任务2”));
executor.submit(() -> System.out.println(“任务3”)); // ❌ 丢弃任务3
🌟 扩展知识
自定义拒绝策略
可以通过实现 RejectedExecutionHandler 接口,定义符合业务需求的拒绝策略,例如记录日志或重新排队。
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(“🚨 任务被拒绝:” + r.toString());
// 可以实现日志记录或任务重新入队的逻辑
}
}
ExecutorService executor = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1),
new CustomRejectedExecutionHandler());
executor.submit(() -> System.out.println(“任务1”));
executor.submit(() -> System.out.println(“任务2”));
executor.submit(() -> System.out.println(“任务3”)); // 🚨 打印拒绝日志
🧩 注意点
选择合适的策略:根据业务场景,选择拒绝策略。例如实时性任务用 AbortPolicy,非关键任务用 DiscardPolicy。
监控线程池:使用 ThreadPoolExecutor 提供的 getQueue() 和 getActiveCount() 方法,定期监控线程池的状态。
希望这些讲解让你既能轻松理解,又能灵活应用!😄
