3

在处理取消的线程中,您经常会看到这样的代码

while (!shutdown) {
  .. do something, if a blocking call, then it will throw the interrupted exception
  try { .. some more ... } 
  catch (InterruptedException e) { 
    shutdown = true; 
  }
}

我想知道的是,这是,还是为什么,比这样做更好

try {
  while (true) {
    .. do something, if a blocking call, then it will throw the interrupted exception
    if (Thread.interrupted()) throw new InterruptedException();
  }
} catch (InterruptedException e) {
  .. clean up, let thread end
}

我的看法是,在后一种情况下,您根本不需要关心 shutdown var。

4

4 回答 4

7

在第一个版本中,您可以与调用代码共享关闭标志(或类似的关闭机制),允许它仅通过设置标志来尝试完全正常关闭,而不会中断线程 - 如果优雅可能会退回到中断关机失败。

我不建议使用线程中断作为唯一的关​​闭机制。

(当然,同样,要小心处理共享标志的方式。你需要使它成为线程安全的;在简单的情况下,一个 volatile 变量可能就足够了。)

于 2011-04-01T12:05:20.440 回答
2

我认为第二种方式更清洁。这是一篇关于同一点的好文章,它还指出了有关线程中断的一些 I/O 考虑因素。 http://www.javaspecialists.eu/archive/Issue056.html

于 2011-04-01T12:10:48.943 回答
2

您不使用异常作为退出条件的一种方式(至少不是通常情况,这是一种最好避免的做法。)异常是针对...提示鼓...宣布异常、错误、情况和典型或潜在不良的条件。

关机不是(通常)错误情况,因此至少从哲学/设计的角度来看,我更喜欢使用关机标志变量的第一个选项。

此外,该标志可以外部化为只读属性(例如,作为 getter)。然后线程外部的组件可以查看线程是否仍然处于活动状态(如果它们具有合法依赖的逻辑。)

就个人而言,我不喜欢 Java 使用 InterruptedException,因为它通常不是一个异常,而是一个信号,通常是一个正常和预期的信号。那好吧。

于 2011-04-01T12:17:13.853 回答
1

我建议您使用 finally 来清理线程(因为它总是被调用),而不是仅仅为了打破循环而抛出异常。尝试

try {
  while (!Thread.interrupted()) {
    .. do something, if a blocking call, then it will throw the interrupted exception
  }
} catch (InterruptedException e) {
  // handle exception
} finally {
  .. clean up, let thread end
}
于 2011-04-01T12:34:26.620 回答