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

Mik*_* B. 4 java concurrency multithreading executorservice java-threads

我有一个代码,其中4个线程同时运行.我想等到所有这4个线程都完成.只有在那之后继续app流程.

我尝试了两种方法:

  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!");
Run Code Online (Sandbox Code Playgroud)

我的问题:

  • 为什么submit(),shutdown()不要等到所有线程都完成并打印«我们已经完成了!所有线程都已完成!»电话结束service.shutdown();

Ada*_*ion 8

答案可以在ExecutorService.shutdown()Javadoc中找到:

此方法不会等待先前提交的任务完成执行.使用awaitTermination来做到这一点.

如果您想等待线程完成工作,您有以下选择:

  • 获取Future实例返回submit()并调用get()每个Future实例
  • 打完电话后shutdownservice通话awaitTerminationservice,直到它返回true
  • 而不是调用submitservice你添加Runnable实例到java.util.List,并通过此列表中invokeAll呼吁方法service

  • 我要添加的另一个选项是等待所有执行完成后,给每个线程一个[`CountDownLatch`]的引用(https://docs.oracle.com/javase/7/docs/api/java/ util/concurrent/CountDownLatch.html)用线程数初始化.在主线程中调用`latch.await()`并让工作线程在完成时调用`latch.countDown()`. (2认同)