Discuss / Java / 疑惑

疑惑

Topic source

为什么HelloThead类里也会抛出 InterruptedException 异常?

如果去掉HelloThead类里行  “break;”

 输出结果变成:

1HELLO

2HELLO

....

interrupted!

end

56HELLO

....

MyThead类里最后不是执行 hello.interrupted了吗,所以有没有"break;"应该都没关系的把

求解!!

廖雪峰

#2 Created at ... [Delete] [Delete and Lock User]

没有break那是死循环

杜康二八

#3 Created at ... [Delete] [Delete and Lock User]

我的理解是,当在MyThread线程中中断HelloThread线程时,HelloThread线程处于sleep的线程等待中,所以直接中断会抛出InterruptedException,需要在捕获的时候退出while循环,不然的话线程并没有被中断(只是处理了捕获异常中的代码),所以会继续运行到天荒地老

瘦明月

#4 Created at ... [Delete] [Delete and Lock User]

楼上老哥说的完全正确,刚开始我也不能理解,为什么去掉break会死循环,看了楼上老哥的思路后,试着在MyThread中打印HelleThread的状态发现确实和楼上说的一致,处于Time Waiting状态(其实也好理解,因为主线程sleep1000ms后,Hello线程又马上sleep100毫秒,在这一百毫米中MyThread对它发起了中断,所以只能靠捕获异常来结束循环了),可以将HelloThread中的sleep删掉,就不会陷入死循环了

wlwheart

#5 Created at ... [Delete] [Delete and Lock User]

若线程在阻塞状态时,调用了它的interrupt()方法,那么它的“中断状态”会被清除并且会收到一个InterruptedException异常。

十分感谢楼上三位的解答。 所以关键其实就在HelloThread中有个sleep(100),这导致该线程不能够被正常MyThead终止,于是在捕获 InterruptedException时候需要加上break。

斗胆解释一下

为什么要break呢? 查看 InterruptedException 源码中的注释:

Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted

也就是说, 某线程被interrupted时, 它恰好在wait,sleep,occupied, 它就会抛出异常, isInterrupted() 也就不会被正常置为false,

 while循环就不能正常中止, 就只能靠break中止. 

(如果不对,请老师指正)

萧雨千叶

#8 Created at ... [Delete] [Delete and Lock User]

实际上MyThread中调用 hello.interrupt() 后,HelloThread中的 isInterrupted() 已经变成了true,

如果此时HelloThread没有在sleep状态,while判断 !isInterrupted() 为false会直接结束线程;

如果此时HelloThread在sleep状态,会直接抛出InterruptedException异常,并清除中断状态,即isInterrupted() 会返回false,如果没有break的话,while会条件会一直返回true,就死循环了;

综上,没有break大概率会导致死循环,但不是一定会死循环,加break是为了保证代码的健壮,所以也是必须要加的。

萧雨千叶

#9 Created at ... [Delete] [Delete and Lock User]

还有一种做法是不使用break,在catch中再调用一次Thread.currentThread.interrupt()恢复中断标志位true,这样while条件判断为false就结束线程了。

楼上说得对,其实就是一个自动清理中断flag的问题


  • 1
  • 2

Reply