Java 线程中断机制

给等待状态线程提供响应机制

中断


调用中断后只是设置了一个中断标记

  • 如果线程运行中,那么不会发生什么,外部逻辑可以检查发现这个标记被设置了,以便进行处理
  • 如果线程在等待中,那么底层会不断轮询标记,发现标记后发起中断,就会抛出检查异常InterruptedException,之后重置标记,让线程恢复运行,以便用户处理异常

注意点

  • 中断不代表线程停止,只是一种协作机制,表示发生了事件,需要处理
  • 线程等待中也可以设置标记,设置标记是对象行为,和运行不相关

实例方法,非线程类一般通过Thread.currentThread()获取当前线程进行操控

  • Thread.currentThread().interrupt() 设置一个标记,表示请求中断
  • Thread.currentThread().isInterrupted() 检查中断标记

静态方法Thread.interrupted()会返回当前中断标记,并且重置标志位

Thread.java
1
2
3
4
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
private native boolean isInterrupted(boolean ClearInterrupted);

捕获到异常后,一定不能忽略,因为标记已经被重置, 忽略会导致中断信息丢失
如果没有处理方案,有两种选择

  • 重新设置中断标记,期待外围有检查中断的逻辑
Sample
1
2
3
4
5
6
7
8
9
10
11
void method() {
try {
if(Thread.currentThread().isInterrupted()){
handleInterrupt();
return;
}
normalThreadAction();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
  • 抛出这个异常,交给外部处理
1
2
3
void method() throws InterruptedException{
normalThreadAction();
}

通常线程会外围循环检查是否中断

1
2
3
4
5
6
7
8
while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出
try{
Thread.sleep(5*1000); //阻塞过程捕获中断异常来退出
}catch(InterruptedException e){
e.printStackTrace();
break; //捕获到异常之后,执行break跳出循环,或者重新设置中断标记让外围检测到
}
}

不支持中断


中断只对Waiting状态有效,对于Block状态无效
一些阻塞IO也无效比如IO中的Socket
Socket调用close()会退出阻塞并抛出异常,提供类似的机制
针对阻塞状态没有通行的方法,取决于具体应用提供机制