为什么 InterruptedException 仅从阻塞方法(如 sleep() 和 wait())中抛出?
Why is InterruptedException thrown only from blocking methods like sleep() and wait()?
如果我写如下代码,我们不能中断或终止线程。它也不会抛出 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 的设计方式使得 InterruptedException 仅在阻塞方法如 sleep() 和 wait() 的情况下被抛出.
为什么在普通代码中,我们需要像我上面的代码片段那样手动处理?为什么每当我们通过 interrupt() 方法将中断标志设置为真时,Java 不会抛出 InterruptedException?
我看了很多关于InterruptedException的博客和文章,但是没有找到有说服力的答案。
编辑
找到关于 InterruptedException 的好文章:
http://codepumpkin.com/interruptedexception-java-multithreading/
Java 的早期版本曾经能够终止线程,但在尝试支持多个操作系统时,这很快成为一个问题。
操作系统有多种不同的方法来实现具有不同功能的线程。
在运行中停止线程被认为是不安全的,这可能会导致应用程序其他部分出现意外行为,例如死锁。
这里有更多详细信息:
https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
1) why Java is designed in such way that InterruptedException is being thrown only in case of blocking methods like sleep() and wait().
thread.interrupt()
的重点在于合作。线程被中断,但它必须使用 Thread.currentThread().isInterrupted()
检查中断标志,以便它可以正确管理自己的终止并在必要时清理共享对象、锁、finally 块等。
引用 tutorial on the subject,强调我的。
An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.
dothrowInterruptedException
的方法都是在等待锁等条件。它们在被中断时抛出异常,因此线程可以在终止前再次清理自身。
2) Why in normal code, we need to handle this manually as in my above code snippet? Why Java is not throwing InterruptedException whenever we set interrupted flag true through interrupt() method?
备选方案是让 InterruptedException
成为一个 RuntimeException
,无论程序是否预期它都可以随时抛出。 stop()
和其他已弃用的 Thread
方法的部分问题是它们往往会违反各种语言结构,并且可能会离开
应用程序内存处于错误状态。这里是 more details about that.
如果是 RuntimeException
,InterruptedException
也是如此。您可以想象,如果一个线程正在更改一个共享对象,然后就在中途抛出一个意外的 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
}
库"swallow"中断标志有很多问题。即使您的代码很小,它也可能会被复制到更大的块中,因此您始终可以将中断标志恢复为良好模式。
如果我写如下代码,我们不能中断或终止线程。它也不会抛出 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 的设计方式使得 InterruptedException 仅在阻塞方法如 sleep() 和 wait() 的情况下被抛出.
为什么在普通代码中,我们需要像我上面的代码片段那样手动处理?为什么每当我们通过 interrupt() 方法将中断标志设置为真时,Java 不会抛出 InterruptedException?
我看了很多关于InterruptedException的博客和文章,但是没有找到有说服力的答案。
编辑
找到关于 InterruptedException 的好文章: http://codepumpkin.com/interruptedexception-java-multithreading/
Java 的早期版本曾经能够终止线程,但在尝试支持多个操作系统时,这很快成为一个问题。 操作系统有多种不同的方法来实现具有不同功能的线程。 在运行中停止线程被认为是不安全的,这可能会导致应用程序其他部分出现意外行为,例如死锁。
这里有更多详细信息: https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
1) why Java is designed in such way that InterruptedException is being thrown only in case of blocking methods like sleep() and wait().
thread.interrupt()
的重点在于合作。线程被中断,但它必须使用 Thread.currentThread().isInterrupted()
检查中断标志,以便它可以正确管理自己的终止并在必要时清理共享对象、锁、finally 块等。
引用 tutorial on the subject,强调我的。
An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.
dothrowInterruptedException
的方法都是在等待锁等条件。它们在被中断时抛出异常,因此线程可以在终止前再次清理自身。
2) Why in normal code, we need to handle this manually as in my above code snippet? Why Java is not throwing InterruptedException whenever we set interrupted flag true through interrupt() method?
备选方案是让 InterruptedException
成为一个 RuntimeException
,无论程序是否预期它都可以随时抛出。 stop()
和其他已弃用的 Thread
方法的部分问题是它们往往会违反各种语言结构,并且可能会离开
应用程序内存处于错误状态。这里是 more details about that.
如果是 RuntimeException
,InterruptedException
也是如此。您可以想象,如果一个线程正在更改一个共享对象,然后就在中途抛出一个意外的 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
}
库"swallow"中断标志有很多问题。即使您的代码很小,它也可能会被复制到更大的块中,因此您始终可以将中断标志恢复为良好模式。