目录
一文彻底搞懂线程中断interrupt导致sleep报InterruptException
问题再现
以下这个场景:
public class ThreadDemo13 {
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
while(!Thread.currentThread().isInterrupted()){
System.out.println("线程");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(3000);
System.out.println("让线程结束");
t.interrupt();
}
}
代码执行到这里,可以看到,代码中出现了一个异常,t线程并没有真的结束!!!
刚才这里的interrupt导致sleep出现异常!!
问题分析
为什么??
我们来理一下思路:t.start()创建了一个新线程,让主线程休眠3秒,为了让线程执行一会,然后主线程想让这个线程结束,就用了interrupt方法。但是结果告诉我们,它只是报了InterruptedException,并且没有结束,而是继续执行了下去。
我们能明确的是:主线程调用interrupt之后,会触发InterruptedException异常。但是程序继续执行了下去==,说明while循环的条件没有被破坏,说明 !Thread.currentThread().isInterrupted() 是true,那就说明 Thread.currentThread().isInterrupted() 是false,说明中断标志位被清除了!!!!!==
原来,在触发InterruptException异常的同时,JVM会同时把线程的中断标志位清除,所以,这个时候在run()方法中判断的 Thread.currentThread().isInterrupted()会返回false,也就不会退出当前while循环了。
问题解决
正确的处理方式应该是在ThreadDemo13类中方法中的while(true)循环中捕获异常之后重新设置中断标志位或者break退出,所以,正确的ThreadDemo13类的代码如下所示。
public class ThreadDemo13 {
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
while(!Thread.currentThread().isInterrupted()){
System.out.println("线程");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
});
t.start();
Thread.sleep(3000);
System.out.println("让线程结束");
t.interrupt();
}
}
这样程序就能正常结束
总结
处理InterruptedException异常时要小心,如果在调用执行线程的interrupt()方法中断执行线程时,抛出了InterruptedException异常,则在触发InterruptedException异常的同时,JVM会同时把执行线程的中断标志位清除,此时调用执行线程的isInterrupted()方法时,会返回false。此时,正确的处理方式是在执行线程的run()方法中捕获到InterruptedException异常,并重新设置中断标志位(也就是在捕获InterruptedException异常的catch代码块中,重新调用当前线程的interrupt()方法)或者直接中断。
如果没有sLeep, interrupt可以让线程顺利结束。
有了sLeep引起了变数!
在执行sLeep的过程中,调用Interrupt,大概率sLeep休眠时间还没到,被提前唤醒了。
提前唤醒,会做两件事:
1.抛出InterruptedException(紧接着就会被catch获取到)
2.清除Thread对象的isInterrupt标志位。
通过Interrupt方法,已经把标志位设为true了,但是sLeep提前唤醒操作,就把标志位又设回false。(此时循环还是会继续执行了)
要想让线程结束,只需要在catch中加上break就行了。
不只是sLeep会清除异常,很多方法都会!!!
标签:Thread,中断,InterruptedException,线程,InterruptException,interrupt,sleep,搞懂 From: https://blog.csdn.net/t1750982356/article/details/143811856