如果我编写如下代码,我们不能中断或终止线程。它也不会抛出InterruptedException。
Thread loop = new Thread(
new Runnable() {
@Override
public void run() {
while (true) {
}
}
}
);
loop.start();
loop.interrupt();
要中断此线程,我需要修改我的代码,如下所示:
Thread loop = new Thread(
new Runnable() {
@Override
public void run() {
while (true) {
if (Thread.interrupted()) {
break;
}
// Continue to do nothing
}
}
}
);
loop.start();
loop.interrupt();
我的问题是,
为什么Java的设计方式只有在阻塞方法如sleep()和wait()的情况下才会抛出 InterruptedException 。
为什么在普通代码中,我们需要像上面的代码片段一样手动处理?每当我们通过 interrupt()方法设置中断标志时,为什么Java不会抛出InterruptedException?
我读过很多关于InterruptedException的博客和文章,但还没有找到令人信服的答案。
修改
在InterruptedException上找到了很好的文章: http://codepumpkin.com/interruptedexception-java-multithreading/
答案 0 :(得分:3)
1)为什么Java的设计方式只有在阻塞方法如sleep()和wait()的情况下才会抛出InterruptedException。
thread.interrupt()
的全部意义在于它是合作的。线程被中断,但它必须使用Thread.currentThread().isInterrupted()
检查中断标志,以便它可以正确管理它自己的终端,并在必要时清理共享对象,锁,最后块等。
引用tutorial on the subject,强调我的。
中断是一个线程的指示,它应该停止它正在做的事情并做其他事情。由程序员确定线程如何响应到中断是,但线程终止是很常见的。
做抛出InterruptedException
的方法是等待锁和其他条件的方法。这些说它们被中断了,所以线程可以在终止之前自行清理。
2)为什么在普通代码中,我们需要像上面的代码片段一样手动处理?每当我们通过interrupt()方法设置中断标志时,为什么Java不会抛出InterruptedException?
替代方案是让InterruptedException
成为RuntimeException
,无论程序是否预期,都可以随时抛出。 stop()
和其他已弃用的Thread
方法的部分问题在于它们往往违反各种语言结构,并且可能会离开
应用程序内存处于不良状态。这是more details about that。
InterruptedException
如果是RuntimeException
,也可以这样说。你可以想象一个线程是在改变一个共享对象,然后只是在中游引发一个意外的RuntimeException
或者完全停止了。正在更新的共享对象很容易处于无效状态。
if (Thread.interrupted()) {
这不是正确的调用方法,因为它会清除线程上的中断标志,这是一个错误的模式。请使用以下内容:
if (Thread.currentThread().isInterrupted()) {
这样可以保留中断标志,如果可能的话应该这样做。此外,当抛出InterruptedException
时,也会清除中断标志。这就是为什么这是一个很好的模式:
try {
...
} catch (InterruptedException ie) {
// re-interrupt the thread to propagate the interrupt flag
Thread.currentThread().interrupt();
// handle the interrupt here by probably quitting the thread
}
库存在“吞下”中断标志的问题很多。即使您的代码很小,它也可能被复制到一个更大的块中,因此您总是可以将中断标志恢复为良好的模式。
答案 1 :(得分:1)
早期版本的Java曾经能够杀死线程,但在尝试支持多个操作系统时很快就成了问题。 操作系统有很多不同的方法实现具有非常不同功能的线程。 在飞行途中停止线程被认为是不安全的,可能导致应用程序的其他部分出现意外行为,例如死锁。
此处有更多详情: https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html