【问题标题】:How to exit ExecutorService after all the threads have done their execution? [duplicate]在所有线程执行完毕后如何退出 ExecutorService? [复制]
【发布时间】:2017-07-12 04:17:21
【问题描述】:

这是有效的代码,但我明确指定了等待时间。当所有线程都完成执行时,有什么方法可以退出ExecutorService

    ExecutorService es = Executors.newCachedThreadPool();
    {
      for(final List<String> list:partitions){

       es.execute(new Runnable() { 
         public void run() {
      try{
            System.out.println(list);
            new CallAPI().make_call(list, access_token);    

        }catch(Exception e){
        System.out.println(e);
        }       
      }
     });
    Thread.sleep(5000);
   }
   boolean finshed = es.awaitTermination(15, TimeUnit.MINUTES);
   es.shutdown();

boolean finshed = es.awaitTermination(15, TimeUnit.MINUTES);==>我在这里给了等待时间,但我不想要这个,因为我不知道线程什么时候完成执行

【问题讨论】:

  • shutdown 和 awaitTermination 的顺序是错误的

标签: java multithreading executorservice executor


【解决方案1】:
  • 使用Future&lt;?&gt; f = executor.submit(new Runnable(...));
  • 将期货存储在列表中
  • 在循环之后,遍历期货并调用f.get()

这将阻塞,直到所有任务都已执行。

然后您可以拨打executor.shutdown()

【讨论】:

  • 感谢您的回复,我会检查一下。
【解决方案2】:

听起来你想要ExecutorService.invokeAll。您所要做的就是将您的列表集合转换为 Callable 集合。

List<Callable<String>> tasks = partitions.stream()
    .map(list->{
         System.out.println(list);
         new CallAPI().make_call(list, access_token);
         return "finished";   
    }).collect(Collectors.toList());

List<Future<String>> futures = es.invokeAll(tasks);
es.shutdown();

那么你就有了future,你可以用它们来检查异常,或者任务是否完成。

【讨论】:

  • 感谢这解决了我的问题
【解决方案3】:

以下方法分两个阶段关闭一个ExecutorService,首先调用shutdown拒绝传入的任务,然后在必要时调用shutdownNow取消任何延迟的任务:

 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();
   }
 }

boolean awaitTermination(长时间超时,TimeUnit 单位) 在关闭请求后阻塞,直到所有任务都完成执行,或者发生超时,或者当前线程被中断,以先发生者为准。

【讨论】:

  • 什么任务需要 3 分钟才能完成?
  • 感谢回复,但我希望所有线程都能正常执行,然后关闭执行器。
【解决方案4】:

要在所有任务完成后终止 ExecutorService,只需调用es.shutdown()。您自己的线程将继续执行,而任务线程将处理所有排队的任务。

来自 Java 文档:

关机 启动有序关闭,其中执行先前提交的任务,但不会接受新任务。如果已经关闭,调用没有额外的效果。 此方法不等待先前提交的任务完成执行。使用 awaitTermination 来做到这一点。

当你想阻塞你自己的线程时,你需要awaitTermination

【讨论】:

    猜你喜欢
    • 2013-04-27
    • 2017-01-24
    • 2022-01-10
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 2015-02-14
    • 2021-09-20
    相关资源
    最近更新 更多