一个方法什么时候应该抛出DistrutedException,我应该如何处理一个这样做的方法?(阻止方法)

如果一个方法一定是一个阻塞方法,那么我认为如果我遗漏了,我就犯了一个错误,这是对的吗?throws InterruptedException

简而言之:

  • 阻塞方法应包括否则是正常方法。throws InterruptedException
  • 阻止方法可能会损害响应能力,因为很难预测何时完成,这就是为什么它需要 。throws InterruptedException

这是对的吗?


答案 1

不,我不认为你的总结是正确的。通常,如果你正在编写一个调用其他抛出的方法,那么你的方法也应该通告抛出 - 除非你有一个很好的计划,当你所依赖的方法信号中断时该怎么办。InterruptedExceptionInterruptedException

你能够接受这种干扰的情况很少见。也许您正在计算一个迭代解决方案,其中精度随时间增加而增加,但是,当您的调用线程中断时,您决定在分配的时间内达到的解决方案足够好,并且仍然足够正确以返回。换句话说,该解决方案仍在方法的范围内。

想象:

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;
}

请注意,我们调用了 ,如果已设置,则具有清除线程中断状态的副作用。如果该方法返回 true,则我们作为调用方已接受保持和传达该中断状态的责任。在本例中,由于我们不假设我们创建了调用线程,并且此处没有足够的可见范围来了解其中断策略是什么,因此我们通过 throwing 传达了我们观察到并采用的中断状态。Thread#interrupted()InterruptedException

将一种方法标记为“阻塞”始终是一个程度问题;每个方法都会阻止其调用方一段时间。您可能正在寻找的区别在于,该方法是否阻止等待某些外部输入,例如用户按键或通过网络到达的消息。在这些情况下,您投放的广告会向调用方指示您的方法可以安全地供必须控制其延迟的线程的调用方使用。你是在说,“这可能需要一段时间才能完成,但它不会比你愿意等待的时间长。你是在说,“我会跑,直到你告诉我不要。这与java.io.InputStream#read()不同,java.io.InputStream#read()威胁要阻塞,直到发生三种情况之一,其中没有一种是调用方的线程被中断。InterruptedException

在大多数情况下,您的决定归结为回答以下问题:

  • 为了满足我的方法的要求,我是否需要调用任何抛出的方法?InterruptedException
  • 如果是这样,到目前为止我所做的工作对我的呼叫者有什么用处吗?
  • 如果没有,我也应该扔.InterruptedException
  • 如果没有我调用 throws,我应该尊重我的调用线程的中断状态吗InterruptedException
  • 如果是这样,我所做的任何工作是否直到我检测到我被打断了对我的呼叫者没有任何用处?
  • 如果没有,我应该扔.InterruptedException

在那些情况下,人们会检测到当前线程的中断并吞下它,通常仅限于您(作者)创建了有问题的线程,并且您已经承诺在线程中断后退出线程的方法。这就是“合作取消”的概念,在这种概念中,您观察到线程停止运行的请求,并且您决定通过尽快完成工作并让线程的调用堆栈展开来遵守该请求。但是,除非您是线程方法的作者,否则吞下线程的中断状态可能会损害调用方及其调用的其他方法的预期行为。run()run()

我建议您研究线程中断状态的主题,并熟悉Thread#isInterrupted(),Thread#interrupted()Thread#interrupt()等方法。一旦你理解了这些,并看到飞行中的存在是返回真实的替代表示,或者是返回真实的礼貌翻译,这一切都应该开始变得更有意义。InterruptedExceptionThread#isInterrupted()Thread#interrupted()

如果您需要更多示例进行研究,请说出来,我可以在这里添加建议。


答案 2

InterruptedException(通常)在方法上被阻塞的线程被调用时被抛出。interrupt()

它的要点是取消阻止(出于某种原因)被阻止的线程。原因示例是应用程序关闭。因此,当您关闭应用程序时,如果您有线程等待,请说或,如果您不告诉他们您正在关闭,他们将继续。如果这些线程不是守护程序线程,则应用程序不会关闭。sleep()wait()wait()

因此,当线程在 期间中断时,您必须检查条件并处理情况。在关机的情况下,您必须检查标志并最终进行清理工作并让线程离开。sleep()shutdown

线程可能会因为其他一些原因而中断,但要点是相同的。如果你有多线程应用程序,你必须为你的线程建立协议,以便他们知道什么时候有一些特殊条件如何处理它。如果线程正在等待/休眠,则必须将其唤醒以处理这种情况。你的库或框架的 clinets 不知道你的协议,所以他们不知道如何处理,因为建议是在你的库/框架代码中处理它。InterruptedException


推荐