【问题标题】:Java ExecutorService ShutdownNow Takes AgesJava ExecutorService ShutdownNow 需要很长时间
【发布时间】:2014-03-21 14:36:18
【问题描述】:

我有一个 Java ExecutorService(固定线程池为 1),我将可运行任务传递给它以供将来执行。每个任务通常在 10 秒内完成。 ExecutorService 只是简单地完成任务。如果我关闭我的应用程序,我会运行以下命令;

if (taskProcessor != null) {
    taskProcessor.shutdownNow();
    while (!taskProcessor.isTerminated()) {
        // Wait For All Submitted Tasks To Finish
    }
}

问题是它似乎需要一段时间才能关闭,有时可能需要几分钟,有时它似乎永远不会关闭,有时它会在几秒钟内关闭!执行程序队列中的任何时候都可能有多达 2000 个任务,但我只是希望它完成当前正在执行的任务并退出。我在这里做错了什么?

【问题讨论】:

  • 忙着等待并不是一个好主意。

标签: java multithreading executorservice java.util.concurrent


【解决方案1】:

您没有按照正确的顺序关闭ExecutorService

您必须按照oracle 推荐的特定顺序致电shutdownshutdownNowawaitTermination

void shutdownAndAwaitTermination(ExecutorService pool) {
   pool.shutdown(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
 }

【讨论】:

    【解决方案2】:

    您可以通过不让您的代码忙于等待来做得更好。这将释放 CPU 以完成任务。并防止对 isTerminated 使用的任何锁的争用。

    【讨论】:

      【解决方案3】:

      这完全取决于正在执行的任务。 ThreadPoolExecutor 在所有任务结束之前不会结束。 shutdownNow() 会中断所有任务,但任务可能会忽略它。

      【讨论】:

      • 谢谢,我将添加一些调试并尝试探索这是否正在发生。我为每个任务附加了一个计时器来监视任务超时,因此想知道这是否是问题发生的地方,并且正在运行的任务由于计时器而忽略了中断。
      • 请注意,只有为中断而设计的任务才能对中断做出反应
      • 我认为这就是问题所在。我只是添加一个 catch InterruptedException 并用一个 while 循环包装任务。希望我的调试会在稍后提供一些进一步的信息。
      猜你喜欢
      • 1970-01-01
      • 2013-09-07
      • 2020-08-26
      • 2014-10-09
      • 2012-11-26
      • 2019-12-27
      • 2017-10-22
      • 2020-11-15
      • 2016-05-19
      相关资源
      最近更新 更多