学习java多线程的时候,我们都知道任务和线程的启动是很容易的,只要调用start方法就可以启动一个线程,大多数时候我们都是让它们运行直到结束或者让它们自行遇到异常而停止,然而,有时候我们可能因为资源或者用户取消等其他原因需要提前中止或者取消线程。要做到让线程安全,快速,可靠的停止下来,并不是一件容易的事,java在设计的时候并没有提供安全的机制来终止线程。只提供中断(Interruption),这是一种协作机制,能够使一个线程终止另一个线程的当前工作。
注意上面所用的Interruption只是一种协作机制,只是通知另一个线程在合适的时候或者可能的情况下停止当前工作。每个Thread 都有一个boolean类型的变量表示中断状态,当中断线程时,线程的中断状态被设置为true,在Thread类中提供很多方法可以设置中断和查询中断状态的方法。
public void interrupt() {.......}而且在调用任何阻塞方法的时候都会检测中断,如果发现中断就会提前返回,并且清除中断状态,抛出InterruptedException异常,表示阻塞操作由于中断而提前结束。jvm并不能保证阻塞方法检测中断的速度,不过在使用过程中发现,响应速度还是非常快的。当线程在非阻塞的状态下中断时,只是设置中断状态,然后根据将被取消的操作来检查中断状态以判断发生了中断,如果不触发InterruptedException,那么中断状态一直保持,并不会真正的中断。
public boolean isInterrupted() {........}
public static boolean interrupted() {...}
再来重新理解一下中断:它并不会真正地中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己。通常,中断是实现取消最合理的方式。
中断策略规定线程如何处理某个中断请求--当发现中断的请求时,应该做哪些工作。规定哪些工作单元对于中断来说是原子操作,以及什么时候响应中断。一般响应和处理中断有两种方法:
1. 传递异常 当发生中断的时候,直接抛出InterruptedException异常,从而使你的方法成为可以中断的阻塞方法。
2.恢复中断状态,从而使调用栈中的上层代码能够对其进行处理。
我们先来看一下第一种,传递异常直接在方法 声明的时候 throws InterruptedException 大多数的情况,我们不知道调用者的中断策略,所以我们不能屏蔽中断请求,比如常规的任务和库代码中都不会屏蔽中断请求。
如果知道我们知道中断策略,那么我们就可以直接捕获InterruptedException异常进行处理。
比如:一个些不支持取消但仍可以调用中断阻塞方法的操作。常用作法:发现中断之后重新尝试,在这种情况下,我们一般要保存中断状态,并且在返回或者方法的最后恢复中断。
boolean interrupted = false;
try {
while(true) {
try {
//业务逻辑
.........
} catch (InterruptedException e) {
interrupted = true;
//重试
}
}
} finally {
//恢复中断
if(interrupted) {
Thread.currentThread().interrupt();
}
}