Java 为什么要在catch InterruptException块中调用Thread.currentThread.interrupt()?
为什么要调用catch块中的方法Java 为什么要在catch InterruptException块中调用Thread.currentThread.interrupt()?,java,multithreading,Java,Multithreading,为什么要调用catch块中的方法Thread.currentThread.interrupt()?这样做是为了保持状态 当捕获并吞下中断异常时,基本上可以防止任何更高级别的方法/线程组注意到该中断。这可能会引起问题 通过调用Thread.currentThread().interrupt(),您可以设置线程的中断标志,以便更高级别的中断处理程序会注意到它并可以适当地处理它 在第7.1.3章:中断响应中对此进行了更详细的讨论。其规则是: 只有实现线程中断策略的代码才能接受中断请求。一般用途的任务和
Thread.currentThread.interrupt()
?这样做是为了保持状态
当捕获并吞下中断异常时,基本上可以防止任何更高级别的方法/线程组注意到该中断。这可能会引起问题
通过调用Thread.currentThread().interrupt()
,您可以设置线程的中断标志,以便更高级别的中断处理程序会注意到它并可以适当地处理它
在第7.1.3章:中断响应中对此进行了更详细的讨论。其规则是:
只有实现线程中断策略的代码才能接受中断请求。一般用途的任务和库代码不应吞没中断请求
我认为这是一个不好的练习,或者至少有点冒险。
通常更高级别的方法不执行阻塞操作,它们永远不会在那里看到中断异常。如果你在每一个你执行可中断操作的地方屏蔽它,你将永远不会得到它
Thread.currentThread.interrupt()
和不引发任何其他异常或以任何其他方式发出中断请求(例如,在线程的主循环中设置interrupted
局部变量)的唯一理由是,您确实无法对异常执行任何操作,与finally
块中的类似
如果您想更好地理解Thread.currentThread.interrupt()
调用的含义,请参阅péter Török的答案。注意:
如何停止等待很长时间(例如等待输入)的线程?
为了使这项技术发挥作用,任何捕捉到中断异常且不准备立即处理的方法都必须重新声明异常,这一点至关重要。我们说重述而不是重述,因为重述异常并不总是可能的如果捕获InterruptedException的方法未声明抛出此(已检查)异常,则应使用以下咒语“重新中断自身”:
这确保了线程将尽快重新释放InterruptedException。我认为这个代码示例让事情变得有点清楚。
完成该工作的班级:
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();
}
}
}
尝试调用中断而不将状态设置回原位。请参阅java文档
如果此线程在调用wait()、join()时被阻塞,
休眠(长),则其中断状态将被清除,并将
接收中断异常
如果该线程在I/O操作中被阻塞,则该线程的中断
状态将被设置,线程将收到
ClosedByInterruptException
如果该线程在选择器中被阻塞,则该线程的中断
将设置状态,并立即从选择返回
手术
如果前面的条件都不成立,那么这个线程的中断
将设置状态
因此,如果您将@Ajay George Answer中的sleepBabySleep()方法更改为I/O操作或仅更改为sysout,则无需将状态设置回原位即可停止程序。(顺便说一句,他们甚至不会抛出InterruptedException)
就像@péter Török所说的那样=>这样做是为了保持状态。(特别是对于抛出InterruptedException的方法)中指出“按照惯例,任何通过抛出InterruptedException
退出的方法都会在退出时清除中断状态。我认为这使答案更清楚地说明了为什么需要保留中断状态。另外值得注意的是,interrupt()
call是在通过其他“传递机制”收到关于此状态的通知后设置中断标志的唯一方法-中断异常
并希望或不能重新抛出它。因此结论是??谢谢。我现在明白你的意思了:我想他的意思是Thread.currentThread().interrupt()
允许您更快地退出线程,因此当捕获到中断异常e
时,线程会立即停止。而如果Thread.currentThread().interrupt()代码>未使用,线程继续执行。。
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();
}
}
}
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();
}
}