【发布时间】:2011-06-21 20:44:43
【问题描述】:
为什么要在 catch 块中调用 Thread.currentThread.interrupt() 方法?
【问题讨论】:
标签: java multithreading
为什么要在 catch 块中调用 Thread.currentThread.interrupt() 方法?
【问题讨论】:
标签: java multithreading
这样做是为了保持状态。
当您捕获InterruptedException 并吞下它时,您基本上可以防止任何更高级别的方法/线程组注意到中断。这可能会导致问题。
通过调用Thread.currentThread().interrupt(),您设置了线程的中断标志,因此更高级别的中断处理程序会注意到它并可以适当地处理它。
Java Concurrency in Practice 在第 7.1.3 章:响应中断中更详细地讨论了这一点。它的规则是:
只有实现线程中断策略的代码才能吞下中断请求。通用任务和库代码不应吞下中断请求。
【讨论】:
InterruptedException 退出的方法在这样做时都会清除中断状态。 我认为这使得为什么您需要保留中断状态的答案更加清晰。
higher-level methods/thread groups 是什么意思?
我认为这个代码示例让事情变得更清楚了。 完成这项工作的班级:
public class InterruptedSleepingRunner implements Runnable {
@Override
public void run() {
doAPseudoHeavyWeightJob();
}
private void doAPseudoHeavyWeightJob() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
// You are kidding me
System.out.println(i + " " + i * 2);
// Let me sleep <evil grin>
if (Thread.currentThread().isInterrupted()) {
System.out.println("Thread interrupted\n Exiting...");
break;
} else {
sleepBabySleep();
}
}
}
protected void sleepBabySleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
Main 类:
public class InterruptedSleepingThreadMain {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new InterruptedSleepingRunner());
thread.start();
// Giving 10 seconds to finish the job.
Thread.sleep(10000);
// Let me interrupt
thread.interrupt();
}
}
尝试在不设置状态的情况下调用中断。
【讨论】:
Thread.currentThread().interrupt(); 允许您更快地退出线程,因此当InterruptedException e 被捕获时,线程会在那里停止。而如果不使用Thread.currentThread().interrupt();,线程会继续执行..
注意:
如何停止长时间等待(例如,等待输入)的线程?
要使这项技术发挥作用,任何捕获中断异常但不准备处理它的方法都必须立即重新声明异常。我们说重新断言而不是重新抛出,因为并不总是可以重新抛出异常。 如果捕获 InterruptedException 的方法未声明抛出此(已检查)异常,则应使用以下咒语“重新中断自身”:
Thread.currentThread().interrupt();
这确保线程将尽快重新引发 InterruptedException。
【讨论】:
我认为这是一种不好的做法,或者至少有点冒险。
通常更高级别的方法不执行阻塞操作,他们永远不会在那里看到InterruptedException。如果你在每一个你执行可中断操作的地方都屏蔽它,你永远不会得到它。
Thread.currentThread.interrupt() 的唯一理由是你真的什么都做不了除了finally 块中的例外情况。
如果您想更好地了解 Thread.currentThread.interrupt() 调用的含义,请参阅 Péter Török 的回答。
【讨论】:
参考java文档
如果该线程在调用 wait()、join() 时被阻塞, sleep(long),则其中断状态将被清除,它会 收到一个 InterruptedException。
如果该线程在 I/O 操作中被阻塞,则该线程的中断 状态将被设置,线程将收到一个 ClosedByInterruptException。
如果该线程在 Selector 中被阻塞,则该线程的中断 状态将被设置,它将立即从选择中返回 操作。
如果前面的条件都不成立,那么这个线程的中断 状态将被设置。
因此,如果您将@Ajay George Answer 中的 sleepBabySleep() 方法更改为 I/O 操作或只是一个 sysout,则无需将状态设置回停止程序。 (顺便说一句,他们甚至不抛出 InterruptedException)
就像@Péter Török 所说 => 这样做是为了保持状态。 (特别是对于会抛出 InterruptedException 的方法)
【讨论】: