Java线程池拒绝策略详解(4种常见策略)

文摘   2024-09-25 12:59   四川  

关注mikechen的架构笔记十余年BAT架构经验倾囊相授


大家好,我是mikechen。

Java线程池拒绝策略是线程池的核心,也是大厂经常考察,下面重点来详解4种Java线程池拒绝策略@mikechen


最新mikechen原创超30万字《阿里架构师进阶专题合集》和《最全大厂面试题及答案总结》,请关注本公众号【mikechen的架构笔记】,后台回复:资料,即可领取。


1.AbortPolicy(默认策略)

默认的拒绝策略,当线程池已满时,直接抛出RejectedExecutionException异常,阻止系统继续执行。

public static class AbortPolicy implements RejectedExecutionHandler {    public AbortPolicy() { }    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {        throw new RejectedExecutionException("Task " + r.toString() +                                             " rejected from " +                                             e.toString());    }}

很简单粗暴,直接抛出个RejectedExecutionException异常,也不执行这个任务了。

适用场景:该策略适合希望立即知道任务被拒绝的情况,并由调用方自行处理异常。

优点:明确任务被拒绝,避免吞掉任务不处理的情况。

缺点:调用方需要处理异常,否则会影响程序的稳定性。

 

2.CallerRunsPolicy(策略)

CallerRunsPolicy在任务被拒绝添加后,会用调用execute函数的上层线程去执行被拒绝的任务。

public static class CallerRunsPolicy implements RejectedExecutionHandler {    public CallerRunsPolicy() { }    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {        if (!e.isShutdown()) {            r.run();        }    }}

在调用execute方法的线程中直接运行被拒绝的任务,可以减缓新任务的流量。

适用场景:适合希望任务总能被执行,并且能减缓提交任务的速度的场景;

优点:保证了任务不会被丢弃,且能有效减缓任务提交的速度;

缺点:调用线程的响应时间可能会增加,因为它要执行任务。


3.DiscardOldestPolicy(策略)

抛弃任务队列中等待时间最长的任务,并尝试重新提交当前被拒绝的任务。

public static class DiscardOldestPolicy implements RejectedExecutionHandler {    public DiscardOldestPolicy() { }    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {        if (!e.isShutdown()) {            e.getQueue().poll();            e.execute(r);        }    }}

DiscardOldestPolicy策略的作用是,当任务呗拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。

适用场景:适合某些任务优先级较高的场景(比如:新的任务更重要),不介意丢弃最早的任务,来腾出队列空间处理最新的任务。

优点:能够让新的任务有机会得到执行。

缺点:可能会丢弃较早的任务,导致系统状态不一致。

 

4.DiscardPolicy(策略)

直接抛弃被拒绝的任务,不做任何处理。

public static class DiscardPolicy implements RejectedExecutionHandler {    public DiscardPolicy() { }    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {    }}

采用这个拒绝策略,会让被线程池拒绝的任务直接抛弃,不会抛弃也不会执行。

适用场景:适合任务不重要的场景,允许丢弃部分任务来保证系统稳定性。

优点:简单有效,避免了任务堆积、和线程阻塞。

缺点:任务被悄悄丢弃,调用方不会感知,可能会导致数据丢失、或状态不一致问题。

以上


最后送大家一个福利:

送我原创超30万字阿里架构师进阶专题合集


以及给大家整理最全大厂Java面试题及答案详解,包含:Java、多线程、JVM、Spring、MySQL、Redis、中间件...等必考题答案详解。


需要以上架构专题&面试答案的同学,加我微信即可领取!


添加时备注:资料






mikechen的架构笔记
十余年BAT架构经验倾囊相授!
 最新文章