其他分享
首页 > 其他分享> > 07 线程池中的四个任务拒绝策略该用哪一个?

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