时间:2021-05-19
使用标志位
很简单地设置一个标志位,名称就叫做isCancelled。启动线程后,定期检查这个标志位。如果isCancelled=true,那么线程就马上结束。
注意的是,isCancelled需要为volatile,保证线程读取时isCancelled是最新数据。
我以前经常用这种简单方法,在大多时候也很有效,但并不完善。考虑下,如果线程执行的方法被阻塞,那么如何执行isCancelled的检查呢?线程有可能永远不会去检查标志位,也就卡住了。
使用中断
Java提供了中断机制,Thread类下有三个重要方法。
每个线程都有个boolean类型的中断状态。当使用Thread的interrupt()方法时,线程的中断状态会被设置为true。
下面的例子启动了一个线程,循环执行打印一些信息。使用isInterrupted()方法判断线程是否被中断,如果是就结束线程。
对线程调用interrupt()方法,不会真正中断正在运行的线程,只是发出一个请求,由线程在合适时候结束自己。
例如Thread.sleep这个阻塞方法,接收到中断请求,会抛出InterruptedException,让上层代码处理。这个时候,你可以什么都不做,但等于吞掉了中断。因为抛出InterruptedException后,中断标记会被重新设置为false!看sleep()的注释,也强调了这点。
记得这个规则:什么时候都不应该吞掉中断!每个线程都应该有合适的方法响应中断!
所以在InterruptedExample例子里,在接收到中断请求时,标准做法是执行Thread.currentThread().interrupt()恢复中断,让线程退出。
从另一方面谈起,你不能吞掉中断,也不能中断你不熟悉的线程。如果线程没有响应中断的方法,你无论调用多少次interrupt()方法,也像泥牛入海。
用Java库的方法比自己写的要好
自己手动调用interrupt()方法来中断程序,OK。但是Java库提供了一些类来实现中断,更好更强大。
Executor框架提供了Java线程池的能力,ExecutorService扩展了Executor,提供了管理线程生命周期的关键能力。其中,ExecutorService.submit返回了Future对象来描述一个线程任务,它有一个cancel()方法。
下面的例子扩展了上面的InterruptedExample,要求线程在限定时间内得到结果,否则触发超时停止。
Future的get方法可以传入时间,如果限定时间内没有得到结果,将会抛出TimeoutException。此时,可以调用Future的cancel()方法,对任务所在线程发出中断请求。
cancel()有个参数mayInterruptIfRunning,表示任务是否能够接收到中断。
要注意,mayInterruptIfRunning=true表示线程能接收中断,但线程是否实现了中断不得而知。线程要正确响应中断,才能真正被cancel。
线程池的shutdownNow()会尝试停止池内所有在执行的线程,原理也是发出中断请求。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Java线程会议如下三种方式结束,结束后就处于死亡状态1、run()或者call()方法执行完成,线程正常结束;2、线程抛出一个未捕获的Exception或Er
本文讲述了在Java中如何创建和结束线程的最基本方法,只针对于Java初学者。一些高级知识如线程同步、调度、线程池等内容将会在后续章节中逐步深入。创建线程创建普
前言:java中的join()方法在多线程中会涉及到,这个方法最初理解起来可能有点抽象,用一两次大概就懂了。简单说就是当前线程等待调用join方法的线程结束才能
java常用的结束一个运行中的线程的方法有3中:使用退出标志,使用interrupt方法,使用stop方法。1.使用退出标志即在线程内部定义一个bool变量来判
一个线程如何知道另一线程已经结束?Thread类提供了回答此问题的方法。有两种方法可以判定一个线程是否结束。第一,可以在线程中调用isAlive()。这种方法由