ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

07 线程池中的四个任务拒绝策略该用哪一个?

2022-03-28 15:32:47  阅读:290  来源: 互联网

标签:策略 该用 队列 拒绝 任务 线程 提交 07


 

四个任务拒绝策略该用哪一个?

 

在前面的课程中,我们学习了提交任务和取消任务,这一节我们来学习,当提交的任务被拒绝时该怎么办?线程池给我们提供了4个任务拒绝策略,

 

 

也就是4个解决办法,这4个策略分别对应4个类,

 

 

而且他们还以内部类的形式存在于所谓的threadPoolExecutor中。不仅如此,他们还实现了同一个接口rejectExecutionhandler,拒绝执行处理器,

 

 

它里面只有一个方法,rejectedExecution,拒绝任务的代码就写在这个方法里面。

该方法有两个参数,一个是被拒绝的任务,还有一个是线程池。如果我们想自定义处理器,但还没想好怎么处理被拒绝的任务,那么你可以抛一个拒绝执行异常,接下来我们来依次了解这个词的策略。

 

 

 

 

 

首先来看第一个策略,discardPolicy,该策略是直接丢弃任务,

 

 

从源码中我们可以看到 rejectedExecution型方法体是空的,

 

 

什么都没做,等同于将任务丢弃。下面我们来演示该策略。在演示之前我把演示思路说一下,为了限制数量和任务数量可控,我们采用threadPoolExecutor的这种原生方式来创建线程值,线程池中的限制数量为1,

 

 

当我们提交一个任务时,它就会被占满,任务队列大小也是一,

 

 

再提交一个任务时,他也会被沾满。

 

 

如此一来,如果我们再提交任务时,其中已经没有可工作的线程了,

 

 

队列中也没有多余的空位任务,只有被拒绝的命运。 

 

 

按照这个思路我们来编写代码,编写一个runnable波任务task,定一个int类型的属性index,用于给任务编号,这样可以看到哪个任务被执行,哪个任务被拒绝,重载构造的方法用于初始化index,任务内容是输出当前线程名称和任务编号。

 

 

接下来我们来执行该任务,使用ThreadPoolExecutor创建线程值,核心限制数为一,最大限制数也是一,说明线程池中只能存在一个线程,空闲线程存活时间为0,时间单位为秒,说明空闲线程不会被销毁任务,对你采用linkedblockingQueue队列长度为一,说明队列中只能存放一个任务任务,拒绝策略,采用discardPolicy,直接丢弃被拒绝的任务,向线程池中提交三个任务,三个任务的编号分别是123使用try-catch捕获拒绝执行异常。 

 

 

写上finally代码块,在finally代码块中关闭线程池,

 

 

至此main方法编写完成,整个例子也编写完成。执行程序观察执行结果,从执行结果来看,程序输出一二

 

 

说明第三个任务没执行被丢弃了。测试结果符合预期。

callerRunsPolicy

看完了第一个策略,再来看下一个策略,callerRunsPolicy。该策略是使用调用者线程直接执行被拒绝的任务。

 

 

从源码中可以看到,当线程池没关闭时,直接调用任务的run方法,而这行代码就是使用调用者的线程执行的,线程池执行任务的途径只有通过execute和submit的方法,所以不会线程池执行的。 

 

 

 

下面我们来演示该策略还是沿用之前的例子,将策略由discardPolicy改为callerRunsPolicy。例子改写完成

 

 

再来执行程序,看看从执行结果来看,程序输出123,并且三是main线程打印的,

 

 

事实证明被拒绝的任务的确是使用调用者的线程执行的,看完了第二个策略。

abroadPolicy

再来看第三个策略,abortPolicy该策略是默认的拒绝策略,

 

 

它的做法是抛出任务拒绝异常。从源码中可以看到方法体中只有一段抛异常的代码,

 

 

下面我们来演示该策略,继续沿用之前的例子,将策略由callerRunsPolicy改为abroadPolicy,因此改写完成,再来执行程序看看。 

 

 

 

从执行结果来看,程序输出1和2,还有拒绝执行异常测试结果符合预期

 

 discardOldestPolicy

。接下来我们再来看看最后一个策略,discardOldestPolicy。该策略是丢弃处于任务队列头部的人物,添加被拒绝的任务,

 

 

从源码中可以看到,当线程池没被关闭时,调用任务队列的poll方法,

 

 

该方的作用是移除队列头部元素,也就是移除队列头部任务,然后将被拒绝的任务重新提交给线程池。

为了演示该策略,我们得改一改之前的任务队列容量,将任务队列容量加一,这样提交的第二个任务就会在队列的头部,第三个任务自然就在第二个任务的后面,此时任务队列被占满,

 

 

在提交任务时会将第二个任务移出队列,第三个任务成为头部任务。 

 第四个任务添加成功,

 

 

按照这个改动来编写代码还是之前的例子。首先将任务队列容量由一改为二,然后将测量由abroadPolicy改为discardOldestPolicy。接着再提交1个任务,一共是提交了4个任务,例子改写完成执行程序看看。

 

 

从执行结果来看,程序输出134,

 

 

果然第二个任务被移出了队列。

总结

最后来总结一下本节内容,本节介绍4个任务拒绝策略,它们的作用这里就不再赘述了。在实际开发中abroadPolicy这种策略用的最多,我一般也是用它。当然了你可以制定任务,拒绝策略。 

 

 

附录:

笔记完整文本:

在前面的课程中,我们学习了提交任务和取消任务,这一节我们来学习,当提交的任务被拒绝时该怎么办?线程池给我们提供了4个任务拒绝策略,也就是4个解决办法,这4个策略分别对应4个类,而且他们还以内部类的形式存在于所谓的threadPoolExecutor中。不仅如此,他们还实现了同一个接口rejectExecutionhandler,拒绝执行处理器,它里面只有一个方法,rejectedExecution,拒绝任务的代码就写在这个方法里面。该方法有两个参数,一个是被拒绝的任务,还有一个是线程池。如果我们想自定义处理器,但还没想好怎么处理被拒绝的任务,那么你可以抛一个拒绝执行异常,接下来我们来依次了解这个词的策略。 首先来看第一个策略,discardPolicy,该策略是直接丢弃任务,从源码中我们可以看到 rejectedExecution型方法体是空的,什么都没做,等同于将任务丢弃。下面我们来演示该策略。在演示之前我把演示思路说一下,为了限制数量和任务数量可控,我们采用threadPoolExecutor的这种原生方式来创建线程值,线程池中的限制数量唯一,当我们提交一个任务时,它就会被占满,任务队列大小也是一,再提交一个任务时,他也会被沾满。如此一来,如果我们再提交任务时,其中已经没有可工作的线程了,队列中也没有多余的空位任务,只有被拒绝的命运。 按照这个思路我们来编写代码,编写一个runnable波任务task,定一个int类型的属性index,用于给任务编号,这样可以看到哪个任务被执行,哪个任务被拒绝,重载构造的方法用于初始化index,任务内容是输出当前线程名称和任务编号。接下来我们来执行该任务,使用ThreadPoolExecutor创建线程值,核心限制数为一,最大限制数也是一,说明线程池中只能存在一个线程,空闲线程存活时间为0,时间单位为秒,说明空闲线程不会被销毁任务,对你采用linkedblockingQueue队列长度为一,说明队列中只能存放一个任务任务,拒绝策略,采用discardPolicy,直接丢弃被拒绝的任务,向线程池中提交三个任务,三个任务的编号分别是123使用try-catch捕获拒绝执行异常。 写上finally代码块,在finally代码块中关闭线程池,至此main方法编写完成,整个例子也编写完成。执行程序观察执行结果,从执行结果来看,程序输出一二说明第三个任务没执行被丢弃了。测试结果符合预期。看完了第一个策略,再来看下一个策略,callerRunsPolicy。该策略是使用调用者线程直接执行被拒绝的任务。从源码中可以看到,当线程池没关闭时,直接调用任务的run方法,而这行代码就是使用调用者的线程执行的,线程池执行任务的途径只有通过execute和submit的方法,所以不会线程池执行的。 下面我们来演示该策略还是沿用之前的例子,将策略由discardPolicy改为callerRunsPolicy。例子改写完成再来执行程序,看看从执行结果来看,程序输出123,并且三是main线程打印的,事实证明被拒绝的任务的确是使用调用者的线程执行的,看完了第二个策略。再来看第三个策略,abortPolicy该策略是默认的拒绝策略,它的做法是抛出任务拒绝异常。从源码中可以看到方法体中只有一段抛异常的代码,下面我们来演示该策略,继续沿用之前的例子,将策略由callerRunsPolicy改为abroadPolicy,因此改写完成,再来执行程序看看。 从执行结果来看,程序输出1和2,还有拒绝执行异常测试结果符合预期。接下来我们再来看看最后一个策略,discardOldestPolicy。该策略是丢弃处于任务队列头部的人物,添加被拒绝的任务,从源码中可以看到,当线程池没被关闭时,调用任务队列的poll方法,该方的作用是移除队列头部元素,也就是移除队列头部任务,然后将被拒绝的任务重新提交给线程池。为了演示该策略,我们得改一改之前的任务队列容量,将任务队列容量加一,这样提交的第二个任务就会在队列的头部,第三个任务自然就在第二个任务的后面,此时任务队列被占满,在提交任务时会将第二个任务移出队列,第三个任务成为头部任务。 第四个任务添加成功,按照这个改动来编写代码还是之前的例子。首先将任务队列容量由一改为二,然后将测量由abroadPolicy改为discardOldestPolicy。接着再提交1个任务,一共是提交了4个任务,例子改写完成执行程序看看。从执行结果来看,程序输出134,果然第二个任务被移出了,队列。最后来总结一下本节内容,本节介绍4个任务拒绝策略,它们的作用这里就不再赘述了。在实际开发中abroadPolicy这种策略用的最多,我一般也是用它。当然了你可以制定任务,拒绝策略。

 

标签:策略,该用,队列,拒绝,任务,线程,提交,07
来源: https://www.cnblogs.com/cj8357475/p/16028399.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有