不,我认为您的摘要不正确。 通常,如果您正在编写一个调用其他抛出 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 的广告向您的调用者表明,您的方法可供来自必须控制其延迟的线程的调用者使用。你是说,“这可能需要一段时间才能完成,但不会比你愿意等待的时间长。”你在说,“我会一直跑,直到你告诉我不要。”这与java.io.InputStream#read() 不同,后者威胁要阻塞直到三个条件之一发生,其中没有一个调用者的线程被中断。
在大多数情况下,您的决定归结为回答以下问题:
- 为了满足我的方法的要求,我是否需要调用任何抛出
InterruptedException 的方法?
- 如果是这样,我到那时为止所做的工作对我的调用者有用吗?
- 如果没有,我也应该抛出
InterruptedException。
- 如果我没有调用任何东西抛出
InterruptedException,我应该尊重我的调用线程的中断状态吗?
- 如果是这样,我是否已经完成了任何工作,直到我检测到我的呼叫者对我的任何使用都被打断了?
- 如果不是,我应该抛出
InterruptedException。
检测到当前线程的中断并吞下它的情况通常仅限于您(作者)创建了有问题的线程,并且您已承诺一旦线程获取退出线程的run() 方法打断了。这就是“合作取消”的概念,其中您观察 request 让您的线程停止运行,并决定通过尽快完成工作并让线程的调用堆栈来遵守该请求放松。同样,除非您是线程 run() 方法的作者,否则您吞下线程的中断状态可能会损害您的调用者以及他们调用的其他方法的预期行为。
我建议你研究线程的中断状态这个话题,并熟悉Thread#isInterrupted()、Thread#interrupted()和Thread#interrupt()这些方法。一旦你理解了这些,并看到 InterruptedException 在飞行中是 Thread#isInterrupted() 返回 true 的替代表示,或者 Thread#interrupted() 返回 true 的礼貌翻译,这一切都应该开始变得更有意义了。
如果你需要更多的例子来学习,请说出来,我可以在这里添加建议。