6.取消任务的cancel方法的一些困惑
上一节我们学习了获取任务的get方法,这节我们来学习取消任务的cancel方法。
看似很简单的一个方法,却因为它的参数让无数开发者产生了疑惑,下面我们来看看是怎么回事。
分析
他有一个布尔类型的参数,如果为true的话,表示尝试中断正在执行任务的线程,也就是调用线程的interrupt的方法。这一点也可以从源码中看到。
如图所示,在这段代码中,当参数为true时,拿到正在执行任务的线程,只要线程不为null,就调用线程的interrupt方法尝试中断它。
源码中没有处理false这种情况,说明参数只有在响应中断线程指令的场景下传出,除此以外,传false。另外,这个参数只对执行中的任务有意义。cancel方法返回一个布尔类型的结果,任务取消成功,返回true,否则返回false。
接下来我们来看看任务的三个时间点,第一个时间点是提交任务的时候,也就是调用submit方法的时候,第二个时间点是任务放入任务队列的时候,第三个时间点是任务完成的时候。从submit提交任务到任务队列这个阶段任务还没有开始执行,
从任务队列到任务完成这个阶段任务正在执行,再往后面就是任务完成。
综上所述,接下来内容可根据各个时间段分为以下三个部分来进行,
第一部分,取消未执行的任务,
第二部分,取消已完成的任务。为什么未执行的任务后面是已完成的任务?因为他们两个比较简单,放在前面介绍。
第三部分,取消正在执行的任务,这一部分稍复杂一些。
取消未执行的任务
首先来看第一部分,取消未执行的任务,并且一个有返回值的任务resulttask。任务内容是计算一加一的值,
接下来我们来执行该任务。首先将任务创建出来,然后创建一个线程池,这里就以单个线程的线程池为例。接着我们向线程池提交两遍task任务,为什么要提交两遍?因为线程中只有一个线程,当我们提交一个任务给他时,他立马执行的,此时我们再提交一个任务给他的话,这个任务会被放入任务队列中,队列中的任务都是未执行的,而我们要取消的未执行的任务都在里面,这就是为什么要提交两个任务的原因。接着刚刚的代码写调用服务器二的参数方法取消第二个任务参数,
传true传false无所谓,因为这个参数只会影响执行中的任务,对未执行的任务没有影响。接受cancel方法的返回值,并输出cancel任务是否取消成功。另外,我们在调用FUTURE2的一次cancel的方法再次确认任务是否真的被取消了,接下来我们来获取第二个任务的执行结果,输出该结果,最后别忘了在finally代码块中关闭线程池,至此main方法编写完成,整个例子也编写完成.
执行程序观察执行结果从执行结果来看,程序输出任务取消成功,
再次确认任务是真的取消成功了。因为任务被取消了,所以使用get方法获取任务结果时会引发任务取消异常。
由此可见,取消未执行的任务时,获取结果会引发任务取消异常。
取消已完成的任务
看完了第一部分,接下来我们再来看看同样比较简单的第二部分。取消已完成的任务还是沿用之前的例子,原来需要提交两个任务,现在只需要提交一个变量名future,future1改为future,然后将代码中所有future2改为future,再将这段取消任务的代码移到输出任务执行结果的下方,至此例子改写完成
执行改写后的程序,观察执行结果,从执行结果来看,程序输出一加一的结果二,任务取消失败,再次。任务真的是取消失败了,由此可见已完成的任务是无法被取消的。
取消正在执行的任务
看完了第二部分,接下来我们再来看稍复杂一点的最后一部分,取消正在执行的任务,他有true和false 2种情况儿,false这种情况要简单一点,所以先演示false。任务还是之前的任务,但要做一点小小的改动,再返回结果之前订一个计数器,然后响应中断线程的指令,
使用while循环无限去判断线程是否被中断,只要线程没被中断,就一直递增i,当线程被中断时,说出i的结果,至此任务改写完成。
执行任务的代码还是沿用之前的,只不过需要将这段取消任务的代码移到获取任务执行结果的上方,移完之后在这段代码的前面输出任务是否完成。
这次例子修改完成执行修改后的程序,观察执行结果,从执行结果来看,任务取消成功,并引发了任务取消异常,虽然任务显示取消成功,但实际上任务并没有停下来。
为什么这么说?因为线程池被关闭以后,
如果任务真的被取消了的话,程序会自动结束,但程序并没有结束,后面还是我们手动的去关闭程序。由此可见,参数为false的情况,即使任务被取消了,但他依然会执行完,如果你调用get方法去获取执行结果的话,还会引发任务取消异常,大家需要注意这一点。
下面我们再来看看参数为true的情况,还是沿用之前的例子,只不过需要将false改为true。
例子改写完成再来看看执行结果
从执行结果来看,程序输出336和任务取消成功以及引发的任务取消异常。336是当ID增到336时被中断,
可以看到程序是自己结束的,大家需要注意的是,参数为true是不是就意味着任务立马结束了?不一定。任务不响应中断线程指令的话会继续执行完。
上述代码会发生无限循环,并且停不下来,从执行结果来看,程序并没有停下来,由此可见,参数为true的情况除了会引发任务取消异常以外,我们还可以响应中断线程指令,若不响应中断线程指令,任务继续执行完。
总结
至此,所有时间段的任务取消情况都演示完毕。最后总结一下本节内容,本节介绍了取消任务的方法,
Cancel他的用法和作用,这里就不再赘述了。
在实际开发中,cancel方法用的挺多的。另外,取消各个时间段的任务的结果如图所示,大家再取消任务的时候需特别注意正在执行的任务他分true和fasle 2种情况,参数是传true还是传false视情况而定。
本文来自博客园,作者:小陈子博客,转载请注明原文链接:https://www.cnblogs.com/cj8357475/p/16023806.html