Java线程池拒绝策略(JDK内置)

什么是拒绝策略?

拒绝策略是一种处理机制,当无法再继续接收和执行任务时,对于新提交的任务,需要做出回应,是丢弃还是继续等待执行?

Java线程池拒绝策略触发时机

当提交的任务数量大于maximumPoolSize + wordQueue时,Java会执行相应的拒绝策略,对于当前提交的任务进行处理。

JDK内置了那些拒绝策略

JDK1.5之后引入了线程池,同时也提供了4种拒绝策略,拒绝策略的接口定义如下

public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

接口定义很明确,当触发拒绝策略时,线程池会调用设置的具体策略,将当前提交的任务和线程池传递给你处理。根据不同的业务场景我们需要做不同的处理。接下来让我们一起来了解一下JDK给我们提供了那些拒绝策略
(1)AbortPolicy 中止策略。

 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());
        }
    }

当我们使用Executor的静态方法创建线程池时,默认采用的拒绝策略就是AbortPolicy策略,该策略执行时会打断线程池的执行流程,并抛出拒绝执行的异常。因为Executor创建线程池时采用的任务队列是无界队列,因此就算内存被撑到爆也不会触发拒绝策略。
中止策略没有特别的应用场景,如果无法处理任务了就直接抛出异常,但是要处理好触发策略时的异常,因为抛出异常后悔打断执行流程。

(2)DiscardPolicy 丢弃策略

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

该策略下的线程池会默默丢掉当前提交的任务,因为方法体为空,所以不做任何处理。DiscardPolicy策略用于对数据完整性要求不高,能够接受任务失败的场景,比如点赞、浏览量、评论等业务场景。

(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策略和DiscardPolicy策略一样都会丢弃任务,只不过DiscardOldestPolicy策略丢弃的是旧的未执行的任务,然后将当前提交的新任务添加线程池中等待执行。
DiscardOldestPolicy策略使用的场景一般是发布消息,和修改消息,当消息发布出去后,还未执行,此时更新的消息又来了,这个时候未执行的消息的版本比现在提交的消息版本要低就可以被丢弃了。因为队列中还有可能存在消息版本更低的消息会排队执行,所以在真正处理消息的时候一定要做好消息的版本比较。
(4)调用者执行策略

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

当执行CallerRunPolicy策略时,只要线程池没有关闭,将任务提交给当前提交任务的线程执行。该策略一般在不允许失败的、对性能要求不高、并发量较小的场景下使用,因为线程池一般情况下不会关闭,也就是提交的任务一定会被运行,但是由于是调用者线程自己执行的,当多次提交任务时,就会阻塞后续任务执行,性能和效率自然就慢了。

这就是JDK内置的四种线程池拒绝策略,创建线程池时我们需要根据不同的业务场景选择不同的拒绝策略。另外除了这四种内置拒绝策略以外,还有很多第三方实现的拒绝策略,比如Dubbo、Netty、activeMq等都提供了拒绝策略的实现。当然也可以根据需求自己实现拒绝策略,只需要实现 RejectedExecutionHandler接口提供处理的具体实现即可。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值