当前位置: 首页 > 知识库问答 >
问题:

ExecutorService的shutdown()不会等到所有线程都将完成

郭意
2023-03-14

我有一个4个线程同时运行的代码。我想等到所有这4个线程都完成。并且只有在那之后才能继续应用程序流程。

我尝试了两种方法:

  1. Thread#join(),此方法按预期工作。在 join() 之后出现的代码仅在所有线程完成后执行。
  2. ExecutorService#shutdown(),这种技术允许执行代码,即使不是所有线程都已完成,也会在 shutdown() 之后执行。

代码示例:

ExecutorService service = Executors.newFixedThreadPool(cpuCoresNum);

for (int i = 0; i < cpuCoresNum; i++) {

    service.submit(() -> {
        try {
            foo(); // some long execution function
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
}

service.shutdown();

System.out.println("We're done! All threads are finished!");

我的问题:

  • 为什么 submit()shutdown() 不要等到所有线程都完成并打印 “我们完成了!所有线程都已完成!» 在调用 service.shutdown();

共有3个答案

壤驷敏学
2023-03-14

感谢@Adam Siemion的建议,以下是最终代码:

ExecutorService service = Executors.newFixedThreadPool(cpuCoresNum);

int itNum = 1;

for (int i = 0; i < cpuCoresNum; i++) {

    int treadID = itNum++;

    service.submit(() -> {
        Thread.currentThread().setName("Thread_#" + treadID);
        try {
            foo();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
}

// wait until all threads will be finished
service.shutdown();
try {
    service.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
    e.printStackTrace();
}
何辰沛
2023-03-14
匿名用户

来自ExecutorService的oracle文档页面的推荐方式:

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

< code>shutdown():启动有序关闭,执行以前提交的任务,但不接受新任务。

关机现在():尝试停止所有正在执行的任务,暂停等待任务的处理,并返回等待执行的任务的列表。

在上面的示例中,如果任务需要花费更多的时间来完成,则可以将if条件更改为while条件

替换

if (!pool.awaitTermination(60, TimeUnit.SECONDS))

具有

 while(!pool.awaitTermination(60, TimeUnit.SECONDS)) {
     Thread.sleep(60000);
 }  

长孙德惠
2023-03-14

答案在< code > executorservice . shut down() Javadoc:

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

如果要等待线程完成工作,可以使用以下选项:

  • 获取submit()返回的Future,并对每个Future实例调用get()
  • 服务上调用关机后,调用service,直到返回true
  • 不要在服务上调用submit,而是将可运行的实例添加到java.util中。列出,并将此列表传递给服务上调用的invokeAll方法

 类似资料:
  • 问题内容: 我有一个代码,其中4个线程同时运行。我想等到所有这4个线程都结束。并且只有在那之后才能继续应用程序流程。 我尝试了两种方法: ,这种方法可以正常工作。之后的代码仅在所有线程完成后才执行。 ,此技术允许执行代码,即使并非所有线程都已完成,也可以执行代码。 代码示例: 我的问题: 为什么并且不要等到所有线程都完成并打印出来 _«我们完成了! 所有线程都完成了!» _刚打完电话? 问题答案:

  • 问题内容: 我需要一次执行一些任务4,如下所示: 全部完成后如何获得通知?现在,我想不出什么比设置一些全局任务计数器并在每个任务结束时减少它,然后无限循环监视此计数器为0更好的了。或获取期货的列表,并在无限循环中对所有期货进行isDone监视。什么是不涉及无限循环的更好的解决方案? 问题答案: 基本上在你致电之后:

  • 我想在C#中处理子目录和文件的文件系统/文件夹。我正在使用TPL库中的任务。这个想法是递归地执行它并为每个文件夹创建一个任务。主线程应该等待子线程完成,然后打印一些信息。事实上我只是想知道扫描何时完成。我已经开始使用线程池,然后切换到TLP。做了一些简单的例子。经过一些尝试从简单的代码到越来越臃肿的代码我被困在这里: 主线程有时仍然过早地继续,而不是在完成所有其他线程之后继续。(我对C#比较陌生,

  • 这可能是在类似的背景下问的,但我在搜索了大约20分钟后找不到答案,所以我会问。 我已经编写了一个Python脚本(比如说:scriptA.py)和一个脚本(比如说scriptB.py) 在scriptB中,我想用不同的参数多次调用scriptA,每次运行大约需要一个小时,(这是一个巨大的脚本,做了很多事情……不用担心),我希望能够同时使用所有不同的参数运行scriptA,但我需要等到所有参数都完成

  • 问题内容: 我将一堆可运行的对象放入ExecutorService中: 我希望我的程序/过程在所有工作人员完成后立即停止。但是根据我的日志,这种情况还需要20到30秒。工人没有分配任何资源,实际上,他们目前什么都不做。 不要误会我的意思,这对我来说不是一个关键问题,我只是想了解正在发生的事情,而且我想知道这是否是正常行为。 问题答案: 使用它的。的javadocs说“每个新线程都被创建 为非守护

  • 问题内容: 我正在编写一个具有5个线程的应用程序,这些线程可以同时从Web获取一些信息,并在缓冲区类中填充5个不同的字段。 当所有线程完成其工作时,我需要验证缓冲区数据并将其存储在数据库中。 我该怎么做(当所有线程完成工作时收到警报)? 问题答案: 我采用的方法是使用管理线程池。