How to Wait for All Threads to Finish, Using Executorservice

Wait for all tasks in ExecutorService.execute to complete

If you read the javadoc of the ExecutorService.awaitTermination (or look at the method signature) you will see it returns a boolean. This boolean indicates if the Executor terminated or not. You can use that information to create a while loop to determine if it has been terminated or not.

ExecutorService executor = ...

executor.shutdown(); // close the executor and don't accept new tasks

while (!executor.awaitTermination(100, TimeUnit.MILLISECONDS) {}

Something like this will stop the executor and wait until it terminated and all tasks have finished.

Await completion of all ExecutorService Threads

When I executed the code above, I was expecting the code to await the completion of the previous threads when running "threadPool.shutdown()"

this won't happen, from ExecutorService's docs:

void shutdown()

Initiates an orderly shutdown in which previously submitted tasks are
executed, but no new tasks will be accepted. Invocation has no
additional effect if already shut down.

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

in order to achieve your result, you need to use both, shutdown() first and then awaitTermination​():

boolean awaitTermination​(long timeout, TimeUnit unit) throws
InterruptedException

Blocks until all tasks have completed execution after a shutdown
request
, or the timeout occurs, or the current thread is interrupted,
whichever happens first.

returns:
true if this executor terminated and false if the timeout elapsed before termination

this behaviour:

I tried using threadPool.awaitTermination(30, TimeUnit.SECONDS)
instead but for a reason I ignore yet, it awaits the full completion
of the 30 seconds before continuing even if all letters have been
printed.

was probably caused by replacing shutdown() with awaitTermination​(). it was waiting on a "non-shutdown" pool. as already said, you need to call shutdown() before awaitTermination​().

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

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

how to make main thread wait for executor service threads to complete

You can use CountDownLatch#await. Eg copied from docs:

CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);

for (int i = 0; i < N; ++i) // create and start threads
new Thread(new Worker(startSignal, doneSignal)).start();

doSomethingElse(); // don't let run yet
startSignal.countDown(); // let all threads proceed
doSomethingElse();
doneSignal.await(); // wait for all to finish

Wait main thread until all the thread pools task complete of ExecutorService?

The method you are looking for exactly is

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException

From the javadocs,

Executes the given tasks, returning a list of Futures holding their
status and results when all complete. Future.isDone() is true for each
element of the returned list. Note that a completed task could have
terminated either normally or by throwing an exception. The results of
this method are undefined if the given collection is modified while
this operation is in progress.

However, you will need to convert Runnable to List<Callable<Void>> to make use of this.

Also, I would use Timeouts for sanity when using the code in production, which has method signature of

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit)
throws InterruptedException

for sanity!



Related Topics



Leave a reply



Submit