• 在之前的文章中我们知道了线程池各个参数的含义,其中有个参数 handler 我们说了是拒绝策略,具体关于线程池的拒绝策略我们这篇文章来分析

  • 首先我们要理解线程池的拒绝策略的作用,它是用来处理当线程池无法继续处理更多的任务时的处理机制,那么首先我们要知道拒绝策略的触发时机,我么们来看下面代码:

1
2
3
4
5
6
7
8
9
ThreadPoolExecutor threadPoolExecutor =
new ThreadPoolExecutor(
1,
2,
1,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);

线程池的拒绝时机

  • 第一种,当我们正常关闭线程池时也就是使用 shutdown 等方法,这时候即使线程池中还有未完成的任务正在执行,但是由于线程池已经关闭,所以这时候我们再继续向线程池提交任务的话就会被拒绝

  • 第二种,当线程池没有能力再继续处理提交的任务,如队列已满,最大线程数达到,这时候线程池就处于饱和状态


在我们需要学习和了解的就是第二种,在实际开发中我们需要解决这种情况,关于线程池运行的流程可以看之前我们文章,也可关注 i-code.online 博客。

拒绝策略

  • 首先我们知道线程池的拒绝策略参数的类型是 RejectedExecutionHandler 类型的,那么我们可以先来了解一下关于这个接口的关系


  • 在上述类图中我们可以看到 RejectedExecutionHandler 接口有四个实现类,同时都提供了无参构造函数,这四个实现类对应了不同的拒绝策略,都有各自的适用场景

  • **AbortPolicy**拒绝策略:这种策略在拒绝任务时,会直接抛出一个类型为 RejectedExecutionExceptionRuntimeException ,让你感知到任务被拒绝了,于是你便可以根据业务逻辑选择重试或者放弃提交等策略。

  • DiscardPolicy 拒绝策略:这种策略是当任务提交时直接将刚提交的任务丢弃,而且不会给与任何提示通知,所以这种策略使用要慎重,因为有一定的风险,对我们来说根本不知道提交的任务有没有被丢弃

  • DiscardOldestPolicy 拒绝策略:这种策略和上面相似。不过它丢弃的是队列中的头节点,也就是存活时间最久的


  • CallerRunsPolicy 拒绝策略:这种策略算是最完善的相对于其他三个,当线程池无能力处理当前任务时,会将这个任务的执行权交予提交任务的线程来执行,也就是谁提交谁负责,这样的话提交的任务就不会被丢弃而造成业务损失,同时这种谁提交谁负责的策略必须让提交线程来负责执行,如果任务比较耗时,那么这段时间内提交任务的线程也会处于忙碌状态而无法继续提交任务,这样也就减缓了任务的提交速度,这相当于一个负反馈。也有利于线程池中的线程来消化任务


快来关注公众号~~ 平时会更新一些干货哈!

欢迎关注公众号“云栖简码”