【问题标题】:shutdown and awaitTermination which first call have any difference?shutdown 和 awaitTermination 哪个第一次调用有什么区别?
【发布时间】:2013-08-25 02:17:49
【问题描述】:

有什么区别

ExecutorService eService = Executors.newFixedThreadPool(2);
eService.execute(new TestThread6());
eService.execute(new TestThread6());
eService.execute(new TestThread6());
eService.awaitTermination(1, TimeUnit.NANOSECONDS);
eService.shutdown();

eService.shutdown();
eService.awaitTermination(1, TimeUnit.NANOSECONDS);

我不太明白shutdown()。此方法不等待先前提交的任务完成执行。是不是意味着shutdown()可以终止已经提交但未完成的任务?我尝试了一些例子,他们没有证明这一点,请给我一个例子。

【问题讨论】:

标签: java multithreading executorservice


【解决方案1】:

您应该先致电shutdown。否则,您可能会等待很长时间,因为 awaitTermination 实际上并没有关闭您的执行程序。

如果你想等待任务完成,而不是等待执行器关闭,那么你应该使用invokeAll

【讨论】:

  • 谢谢,但是为什么要等很长时间?你能给我举个例子解释一下吗?
  • @user2245634 awaitTermination 实际上并没有首先关闭您的执行程序。因此,除非另一个线程关闭执行程序,否则awaitTermination 将一直坐在那里,直到超时用完。显然,在您的示例中,您在超时前只等待了 1 纳秒,这就是为什么您没有观察到“非常长时间”。
  • 谢谢,我明白了,并且在shutdown() api中:这个方法不等待之前提交的任务完成执行。这意味着也许 shutdown() 可能会终止已提交但未完成的任务?但我尝试了一些示例并不能证明这一点
  • 请注意,shutdown() 不会中断已经执行的任务。来自 javadoc :“启动有序关闭,其中执行先前提交的任务,但不会接受新任务。”如果你想打断你应该打电话给shutDownNow()
  • @AmrishPandey 不,这不是文档所说的。请参阅 S.D. 的回答。你所描述的就是 shutdownNow 所做的。
【解决方案2】:

阅读文档总是有帮助的:

shutdownNow

尝试停止所有正在执行的任务,停止处理 等待任务,并返回正在等待的任务列表 执行。这些任务从任务队列中被排空(删除) 从此方法返回。

此方法不会等待主动执行的任务终止。 使用 awaitTermination 来做到这一点。

除了尽力停止处理之外,没有任何保证 积极执行任务。此实现通过取消任务 Thread.interrupt(),所以任何无法响应中断的任务 可能永远不会终止

shutdown:

启动有序关闭,其中之前提交的任务被 已执行,但不会接受任何新任务。 调用没有 如果已经关闭,则附加效果。

此方法不等待之前提交的任务完成 执行。使用awaitTermination 来执行此操作。

awaitTermination:

在关闭请求后阻塞直到所有任务完成执行,或者发生超时,或者当前线程被中断, 以先发生者为准。

【讨论】:

  • 我不理解关机的文档。它首先说“执行了先前提交的任务”,然后说“此方法不等待先前提交的任务完成执行”。那么,我的任务会完成吗?
  • @jrahhali 表示方法调用立即返回。 IE。调用shutdown 的线程不会阻塞。
  • 啊,不阻塞。现在这是有道理的。他们应该使用这个词而不是等待。谢谢。
  • 对@SD 的回答稍作修改。他们说“shutdown 不会等待先前提交的任务完成执行”,我相信他们的意思是当前线程在先前提交的任务之前 阻塞完成执行。
【解决方案3】:

shutdown 表示执行器服务不再接收传入任务。

awaitTermination 在关闭请求后调用。

您需要先关闭服务,然后阻塞并等待线程完成。

如果你想看到所有的线程都运行完并且坚持使用awaiTermination,你需要把timeout参数设置的足够大。所以你可以这样做:

eService.shutdown();
if (!eService.awaitTermination(60000, TimeUnit.SECONDS))
    System.err.println("Threads didn't finish in 60000 seconds!");
}

或者,您可以这样做:

eService.shutdown();
while (!eService.isTerminated()) {

}

这样您就可以确保所有线程都完成运行,除非它们被意外中断。

【讨论】:

  • 你的意思可能是毫秒...... 60000s 是 16.666 小时。
  • 不要像第二个代码 sn-p 那样忙等待。只是。不要。
  • 最后一个代码块是我来的。非常感谢你
  • @ahrooran 正如@Alexander 所说,您不应使用第二个块。这种空体while 循环被称为“忙等待”,它将保持 CPU 核心在 100% 直到它完成。考虑到您有可用的 awaitTermination 方法,这是一种浪费。
  • @IgorRodriguez 是的。但我需要系统的最后一点性能。我必须对程序进行基准测试
【解决方案4】:

主要区别

关机()-

1. Doesn't block the calling a thread i.e. the thread who called the shutdown().
2. Excecutor doesn't accept any new task after calling shutdown().

awaitTermination() -

1. Blocks the calling thread. (as join() method do)

混淆点:- 如果shutdown()没有杀死之前提交的任务,为什么还需要awaitTermination()?

awaitTermination 意味着等待任务完成/终止,对吧? shutdown() 也在做同样的事情——等待已经与正在运行的任务一起提交的任何任务继续直到完成/终止,那么为什么要使用另一种方法 awaitTermination(..)?下面是解释:

假设你可以等待 10 分钟 来完成所有提交的任务,然后想调用 shutdownNow()(---你已经知道它做了什么) 然后使用 @987654326 @在调用shutdown()之后。

注意awaitTermination(long timeout, TimeUnit unit) 中的方法参数。这个超时是这里的关键。

如果没有时间限制,shutdown() 就可以了。不需要 awaitTermination()。

【讨论】:

  • 恕我直言,而不是 awaitTermination(long timeout, TimeUnit unit),shutdown(long timeout, TimeUnit unit) 不会那么混乱。然后不必先调用shutdown(),然后再调用awaitTermination(..)。任何人都可以启发单独方法背后的逻辑而不是重载 shutdown() 吗?
  • 如果 awaitTermination 退出块并且仍有任务在运行怎么办?在继续之前,您如何确保池中的所有任务都已终止/终止(如果达到超时)?
  • 正如我在回答中提到的,我们只是在调用 shutdownNow() 之前调用 awaitTermination,给池中的任务一些时间来执行或完成。如果它们没有在给定的时间内完成,您将关闭执行器
【解决方案5】:

最佳实现:

executor.shutdown();
try {
    if (!executor.awaitTermination(3500, TimeUnit.MILLISECONDS)) {
        executor.shutdownNow();
    }                   
} catch (InterruptedException e) {              
    executor.shutdownNow();
}
        

【讨论】:

    【解决方案6】:

    在我们启动第一个任务后,ThreadPoolExecutor 会启动一个即使任务完成也不会结束的线程。至少对于固定线程池来说是这样。这就是为什么我们需要调用shutdown。关闭后,ThreadPoolExecutor 将拒绝任何新任务,但将等待正在运行的任务完成,然后允许线程结束。这就是为什么我们在shutdwon 之后需要awaitTermination。

    【讨论】:

      【解决方案7】:
      executorService.execute(runnableTask);  
      
      //executorService.shutdown(); //it will make the executorService stop accepting new tasks
      //executorService.shutdownNow(); //tires to destroy the executorService immediately, but it doesn't guarantee that all the running threads will be destroyed at the same time. This method returns list of tasks which are waiting to be processed.
      //List<Runnable> notExecutedTasks = executorService.shutdownNow(); //this method returns list of tasks which are waiting to be processed.developer decide what to do with theses tasks?
      
      //one good way to shutdown the executorService is use both of these methods combined with the awaitTermination
      executorService.shutdown();
      try{
          if(!executorService.awaitTermination(1000, TimeUnit.MICROSECONDS)) {
              executorService.shutdownNow();
          }
      }catch (InterruptedException e){
          e.printStackTrace();
      }
      

      【讨论】:

        【解决方案8】:

        来自 Java8 ThreadPool 的 awaitTermination 方法:

            try {
                for (;;) {
                    if (runStateAtLeast(ctl.get(), TERMINATED))
                        return true;
                    if (nanos <= 0)
                        return false;
                    nanos = termination.awaitNanos(nanos);
                }
            } finally {
                mainLock.unlock();
            }
        

        首先会检查线程池的运行状态。如果线程池没有关闭(将运行状态设置为终止),awaitTermination 方法将不会返回,直到超时。这解释了如果先等待然后关闭,为什么要等待很长时间。

        【讨论】:

          【解决方案9】:

          你需要在awaitTermination()方法调用发生后调用shutdownNow()方法。那么awaitTermination()方法的实际用法只有你自己才能知道了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-09-01
            • 1970-01-01
            • 2012-01-16
            • 2011-09-16
            • 2019-11-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多