【问题标题】:Java's executionService.shutdownNow() not cancelling or interrupting threadJava executorService.shutdownNow() 不取消或中断线程
【发布时间】:2016-06-09 03:38:41
【问题描述】:

此代码永久阻止 future.get()。我本来期望CancellationExceptionInterruptedException。谁能解释一下?

ExecutorService es = Executors.newSingleThreadExecutor();

es.execute(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {/*squelch*/}
});

Future<Integer> future = es.submit(() -> 1);
es.shutdownNow();
try {
    future.get();
} catch (ExecutionException e) {e.printStackTrace();}

docs 说没有保证,但我仍然觉得观察到的行为很奇怪,因为它暗示停止失败是由行为不端的线程引起的。在这种情况下,似乎没有任何尝试停止线程。

除了尽力停止处理正在执行的任务之外,没有任何保证。例如,典型的实现将通过 Thread.interrupt() 取消,因此任何未能响应中断的任务都可能永远不会终止。

【问题讨论】:

  • future 任务永远不会启动,但第一个任务确实会被中断。所以有一个尝试停止线程。

标签: java multithreading concurrency future executorservice


【解决方案1】:

在这种情况下,似乎没有任何尝试停止线程。

它试图停止运行Runnables。在这种情况下,那可能是正在睡觉的那个。它将被中断,您将捕获异常并返回。 nop Runnable 仍在队列中。

除非调用future.get() 的线程被中断,否则您不会得到InterruptedException

CancellationException 是合理的预期,除了技术上,您没有取消 Future,而是关闭了执行程序。

预期的用途似乎是您零售Runnables shutdownNow() 退货列表,以便您可以运行它们。这行得通,但是您不能根据您提交的内容检查它们,因为它们实际上已经过装饰(但您不知道这一点,而且它没有返回您提交的参考资料,这有点令人惊讶)。

有两个不好的解决方法来获得此功能:跟踪您返回的期货并自行取消它们,或者将 shutdownNow() 返回的 Runnables 转换为期货并取消它们,但这只会起作用,因为这恰好是您正在使用的执行器的内部实现。

所以是的,这就是行为,技术上是正确的,但有点奇怪。你想在这里完成什么?

【讨论】:

  • 感谢您的解释。回复:“你想要完成什么”......什么都没有。我只是在玩。
猜你喜欢
  • 1970-01-01
  • 2014-08-16
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多