ExecutorService's shutdown() doesn't wait until all threads will be finished

Mike B. picture Mike B. · Apr 2, 2016 · Viewed 7.7k times · Source

I have a code where 4 threads run at the same time. I want to wait until all these 4 threads will be finished. And only after that to continue the app flow.

I tried two approaches:

  1. Thread#join(), this approach works as expected. The code, which comes after join() is executed only after all threads are finished.
  2. ExecutorService#shutdown(), this technique allows executing code, which comes after shutdown() even if not all threads are finished.

Code sample:

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!");

My question:

  • Why submit() and shutdown() don't wait until all threads will be finished and prints «We're done! All threads are finished!» right after call of service.shutdown();?

Answer

Adam Siemion picture Adam Siemion · Apr 2, 2016

The answer is available in the ExecutorService.shutdown() Javadoc:

This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.

If you want to wait for the threads to finish work you have the following options:

  • get Future instances returned by submit() and call get() on every Future instance
  • after calling shutdown on service call awaitTermination on service until it returns true
  • instead of calling submit on service add your Runnable instances to a java.util.List and pass this list to the invokeAll method called on service