如何正确处理线程中断

时间:2013-09-05 08:55:23

标签: java multithreading interrupt

我正在开发一个应用程序,它在某个时候启动了一个工作线程。此线程的行为将根据用于启动它的参数而有很大差异,但以下属性列表适用:

  • 它将执行一些次要的I / O操作
  • 它会花费很少时间在第三方图书馆
  • 它可能会为某个子任务创建一些工作线程(这些线程在任务完成后不会被重用)
  • 它会花费最多的时间来处理数字(没有阻止调用)

由于可能持续时间很长(5分钟到几个小时,具体取决于输入),我们希望能够中止计算。如果我们选择中止它,我们不再关心输出,并且线程实际上只要它继续运行就浪费宝贵的资源。由于代码在我们的控制之下,the advised way将使用中断来指示中止。

虽然Web上的大多数示例都涉及循环某种方法的工作线程,但对我来说情况并非如此(similar question here)。此工作线程中的阻塞调用也很少,在这种情况下this article建议手动检查中断标志。我的问题是:如何处理此中断?

我看到了几个选项,但无法确定哪种选择最“干净”。尽管我有一些实际的例子,但我主要对如何处理这个问题的“最佳实践”感兴趣。

  1. 抛出某种未经检查的异常:这会以快速简便的方式终止该线程,但它让我想起了已弃用的ThreadDeath方法使用的Thread#stop()方法及其所有ThreadDeath方法3}}。我可以看到这种方法在拥有的代码中是可接受的(由于已知的逻辑流程),但在库代码中却没有。
  2. 抛出某种经过检查的异常:这将以快速简便的方式终止线程,并通过强制程序员处理此事件来缓解InterruptedException类问题。但是,它给代码带来了很大的负担,需要在任何地方提到异常。有理由不是所有事情都会引发NullPointerExceptions
  3. 使用“目前为止最佳结果”或空结果退出方法。由于涉及的课程数量,这将是一项非常艰巨的任务。如果不够谨慎,{{1}}可能会出现空结果,导致与第1点相同的问题。在大型代码库中几乎不可能找到这些原因。

2 个答案:

答案 0 :(得分:1)

我建议您定期检查Thread.currentThread()。isInterrupted(),如果设置了,可以安全地停止和停止。

您可以在检查此标志并抛出自定义未经检查的异常或错误的方法中执行此操作。

答案 1 :(得分:0)

如何使用ExecutorService来执行Runnable?查看可以指定超时的方法。 E.g。

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
executor.shutdown();

此处任务当然实现了Runnable。