Java 什么时候一个方法应该抛出InterruptedException,我应该如何处理一个抛出InterruptedException的方法?(分块法)
如果一个方法必须是阻塞方法,那么如果我离开,我的想法对吗 outJava 什么时候一个方法应该抛出InterruptedException,我应该如何处理一个抛出InterruptedException的方法?(分块法),java,multithreading,exception-handling,blocking,Java,Multithreading,Exception Handling,Blocking,如果一个方法必须是阻塞方法,那么如果我离开,我的想法对吗 out抛出InterruptedException,我犯了一个错误 简言之: 阻塞方法应包括抛出InterruptedException,否则为正常方法 阻塞方法会影响响应性,因为很难预测它何时完成,这就是为什么它需要抛出InterruptedException 正确吗?如果您的方法阻塞,它应该捕获并处理InterruptedException,并且不希望重新抛出它 此外,该方法可能会在多个位置阻塞-每个位置都应该捕获并处理Inter
抛出InterruptedException
,我犯了一个错误
简言之:
- 阻塞方法应包括
,否则为正常方法抛出InterruptedException
- 阻塞方法会影响响应性,因为很难预测它何时完成,这就是为什么它需要
抛出InterruptedException
正确吗?如果您的方法阻塞,它应该捕获并处理
InterruptedException
,并且不希望重新抛出它
此外,该方法可能会在多个位置阻塞-每个位置都应该捕获并处理InterruptedException
,处理方式应适合于抛出该方法的位置
关于多线程代码的圣经是。我强烈建议你读一读
编辑:
在设计并发代码时,请意识到:
- 根据JVM规范,
可能会被JVM无缘无故地随机抛出(称为“虚假唤醒”)InterruptedException
- 许多线程可能在相同的条件下等待,所有线程都可能被唤醒(例如通过
),但只有一个线程在中断时可以前进notifyAll()
因此,正确编写的并发代码应该捕获
InterruptedException
。您可以选择重新抛出它或抛出自己的特定于应用程序的异常。“应用程序代码”方法应该更倾向于抛出“应用程序”异常,但是,如果等待的代码可能发现自己处于无法找出“哪里出了问题”的状态,那么您唯一的选择就是抛出InterruptedException
InterruptedException
通常是当方法上被阻塞的线程被调用interrupt()
时引发
它的目的是(出于某种原因)解除阻塞被阻塞的线程。原因的例子是应用程序关闭。因此,当您关闭应用程序时,如果有线程等待,比如说sleep()
或wait()
,如果您不告诉他们您正在关闭,他们将继续wait()
。如果这些线程不是守护进程线程,则应用程序不会关闭
因此,当线程在sleep()
期间中断时,您必须检查条件并处理这种情况。在关机的情况下,您必须检查shutdown
标志,并最终执行清理工作,然后释放线程
线程可能会因为其他原因而中断,但要点是相同的。
如果您有多线程应用程序,您必须为您的线程建立协议,以便它们知道何时有一些特殊情况如何处理。如果线程正在等待/休眠,您必须唤醒它来处理这种情况。
您的库或框架的客户端对您的协议一无所知,因此他们不知道如何处理中断异常,因为建议在库/框架代码中处理它。不,我认为您的摘要不正确。通常,如果您正在编写一个调用其他抛出
InterruptedException
的方法,那么您的方法也应该宣传抛出InterruptedException
——除非您有一个很好的计划,当您的方法依赖于信号中断时该怎么办
在这种情况下,你将能够吸收这种干扰是罕见的。也许您正在计算一个迭代解,其中精度随着时间的推移而增加,但是,当调用线程被中断时,您确定在分配的时间内得到的解足够好,并且仍然足够正确,可以返回。换句话说,该解决方案仍然在方法的范围内
想象一下:
private double improveUpon(double start) throws InterruptedException {
// ...
}
public double compute() {
double result = 0.0;
try {
do {
result = improveUpon(result);
} while (couldBeImproved(result));
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
return result;
}
或者,如果您只想尊重中断请求,则可以在不涉及InterruptedException
的情况下:
private double improveUpon(double start) {
// ...
}
public double compute() {
final Thread current = Thread.currentThread();
double result = 0.0;
do {
result = improveUpon(result);
} while (couldBeImproved(result) &&
!current.isInterrupted());
return result;
}
对于另一个变体,请考虑您的方法必须完成其所有的工作或向呼叫者指示它不能完成它的情况,并且需要一段时间才能到达那里,但是您要尊重线程中断。这样就足够了:
private double improveUpon(double start) {
// ...
}
public double compute() throws InterruptedException {
final Thread current = Thread.currentThread();
double result = 0.0;
do {
if (current.interrupted())
throw new InterruptedException();
result = improveUpon(result);
} while (!isAdequate(result));
return result;
}
请注意,我们调用了Thread#interrupted()
,其副作用是,如果设置了线程的中断状态,则会清除该线程的中断状态。如果该方法返回true,那么作为调用方,我们已经接受了保持和传递中断状态的责任。在这种情况下,由于我们没有假设我们创建了调用线程,并且我们在这里没有足够的可见范围来知道它的中断策略是什么,因此我们通过抛出InterruptedException
来传达我们观察到并采用的中断状态
将方法标记为“阻塞”始终是一个程度问题;每个方法都会在一段时间内阻塞其调用者。您可能要寻找的区别是,该方法是否阻止等待某些外部输入,例如用户按键或通过网络到达的消息。在这些情况下,您抛出的InterruptedException
广告向调用者表明,您的方法对于来自必须控制其延迟的线程的调用者来说是安全的。你说的是,“这可能需要一段时间才能完成,但不会超过你愿意等待的时间。”你说的是,“我会一直运行,直到你告诉我不要这样做。”这不同于,比方说,它可能会阻塞,直到三种情况中的一种出现,其中没有一种情况是调用方的线程被中断
在大多数情况下,您的决定归结为回答以下问题:
- 到