【问题标题】:How to properly handle thread interrupts如何正确处理线程中断
【发布时间】:2013-09-05 08:55:22
【问题描述】:

我正在开发一个在某些时候启动工作线程的应用程序。该线程的行为会因启动它所使用的参数而有很大差异,但适用以下属性列表:

  • 它会做一些小的 I/O 操作
  • 它将在 3rd 方库中花费少量时间
  • 它可能会为某个子任务创建一些工作线程(这些线程在他们的任务完成后不会被重用)
  • 它将花费大部分时间处理数字(不存在阻塞调用)

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

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

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

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

【问题讨论】:

  • 您可能会尝试在您的中断处理程序或处理程序中简化 (3);尽管如此,考虑将其与某种 RuntimeException 结合起来可能是一个好主意。

标签: java multithreading interrupt


【解决方案1】:

我建议您定期检查 Thread.currentThread().isInterrupted() 在您知道是否可以安全停止并停止设置的点。

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

【讨论】:

  • 只有在所有运行代码都在您的控制之下时,您才知道安全停止点。如果代码用于库,您将如何处理? (请参阅我的问题中的第 1 点)
【解决方案2】:

使用 ExecutorService 来执行 Runnable 怎么样?查看可以指定超时的方法。例如

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

这里的Task当然实现了Runnable。

【讨论】:

  • 这个答案告诉我如何在工作线程中创建中断,但不告诉我应该如何处理它们——这是我的实际问题。
猜你喜欢
  • 2023-03-18
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-15
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
相关资源
最近更新 更多