0


线程池的拒绝策略

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

  1. 面对自动创建线程会面临的诸多像线程创建启动过多,核心线程数量使用完后对于后续线程的加入,线程池提供了四种拒绝策略,为了便于后续学习,我对其做了一些简单的总结。

一、线程池是什么?


  1. 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。而线程拒绝策略则是线程管理线程,防止线程运行过多而采取的一种管理策略。

二、测试展示:

  1. 为了提高线程的可靠性,Java标准类库引入了一个**RejectedExecutionHandler**接口,用于封装被拒绝任务的处理策略。可以通过线程池的构造器参数**handler**,或者**setRejectedExecutionHandler**方法来为线程池关联一个**RejectedExecutionHandler。**

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);

  1. handler:线程池饱和时,封装被拒绝任务的处理策略
  2. 抽象方法:abstract void rejectedExecution(Runnable r,ThreadPoolExecutor executor);
  3. r代表被拒绝的任务,executor代表拒绝任务r的线程池实例。

1.关于RejectedExecutionHandler操作说明


  1. 1. 当客户端提交的任务被拒绝时,线程池所关联的RejectedExecutionHandler
  2. rejectedExecution方法会被线程池调用。
  3. 2.ThreadPoolExecutor自身提供了几个现成的RejectedExecutionHandler
  4. 接口的实现类。其中ThreadPoolExecutor.AbortPolicy
  5. ThreadPoolExecutor使用的默认RejectedExecutionHandler
  6. 3. 如果默认的RejectedExecutionHandler(它会直接抛出异常)无法满足要求,
  7. 那么我们可以优先考虑ThreadPoolExecutor自身提供的其他
  8. RejectedExecutionHandler,其次才去考虑使用自身实现的
  9. RejectedExecutionHandler接口。

2.其他实现类的表现:


  1. 实现类 所实现的处理策略
  2. ThreadPoolExecutor.AbortPolicy 直接抛出异常
  3. ThreadPoolExecutor.DiscardPolicy 丢弃当前被拒绝的任务(而不抛出任何异常)
  4. ThreadPoolExecutor.DiscardOldestPolicy 将工作队列中最老的任务丢弃,然后重新 尝试接纳被拒绝的任务
  5. ThreadPoolExecutor.CallerRunsPolicy 在客户端线程中执行被拒绝的任务

*/

1.AbortPoilcy( 直接抛出异常):

测试代码

  1. public static void main(String[] args) throws Exception{
  2. int corePoolSize = 5;
  3. int maximumPoolSize = 10;
  4. long keepAliveTime = 5;
  5. //创建阻塞队列队列为10
  6. BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(10);
  7. //调用AbortPoilcy
  8. RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
  9. //创建线程池
  10. ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
  11. Runnable r = () -> System.out.println(Thread.currentThread().getName() + " is running");
  12. for(int i=0; i<100; i++) {
  13. try {
  14. executor.execute(r);
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. //关闭线程池
  20. executor.shutdown();
  21. }

运行结果展示

  1. 使用execute()提交任务,会抛出运行期异常,java.util.concurrent.RejectedExecutionException:如果没有执行异常抛出的话,不会执行一百次线程,可自行测试下,很容易在控制台console中能查看到。

2.DiscardPolicy(丢弃当前被拒绝的任务(而不抛出任何异常)

  1. 当任务添加到线程池中被拒绝时,默认情况下它将丢弃被拒绝的任务。(即该策略下,直接丢弃任务,什么都不做)
  1. //同上,只给出要修改的部分,其他测试主题不变
  2. RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();

运行结果展示:

可以看到旁边是没有滚动条,所以,显而易见的,他并没有一百条线程执行结果,有一部分被直接进行丢弃,也没有抛出异常,


** 3、DiscardOldestPolicy()**

  1. DiscardOldestPolicy策略的作用是,当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。
  1. RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();

运行结果展示

从上面运行结果控制台上的滚动条展示效果,也没有达到一百条运行结果,所以,这种拒绝策略也进行了线程的拒绝,


4、CallerRunsPolicy(在客户端线程中执行被拒绝的任务)

  1. //,只需要将拒绝策略代码改为,主体代码不变。查看运行结果
  2. RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

运行结果如下:

  1. 运行后,在控制台console中能够看到的是,会有一部分的数据打印,显示的是 main is running”,


总结

  1. 线程池的构造函数中所表现的,拒绝策略是一种管理线程运行的策略,对当前线程的调度,对后续线程的接受和使用,现场城池的高效,有很大一部分是由线程池的拒绝策略实现的,四种拒绝策略是相互独立无关的,选择何种策略去执行,还得结合具体的场景。实际工作中,一般直接使用 ExecutorService 的时候,都是使用的默认的 defaultHandler ,也即 AbortPolicy 策略。
标签: java 开发语言

本文转载自: https://blog.csdn.net/m0_65004039/article/details/126443886
版权归原作者 来日方长。。。。long 所有, 如有侵权,请联系我们删除。

“线程池的拒绝策略”的评论:

还没有评论