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.
How to wait for all threads to finish, using ExecutorService?
Basically on an ExecutorService
you call shutdown()
and then awaitTermination()
:
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
...
}
Java executor service: Waiting for all tasks to finish
try-with-resources in Project Loom
You asked:
What I want to achieve is that 'while' loop goes to next iteration only when all tasks submitted to executor in current iteration are finished.
Project Loom promises to make this simpler.
One of the changes brought by Project Loom is that the ExecutorService
interface is a sub-interface of AutoCloseable
. This means we can use try-with-resources syntax. The try-with-resources automatically blocks until all submitted tasks are done/failed/canceled — just what you asked for.
Also, the executor service is automatically shut down when exiting the try
. These changes mean your code becomes simpler and clearer.
Also, for code that blocks often, such as database access, you will see dramatically faster performance using virtual threads (a.k.a. fibers). Virtual threads is another new feature of Project Loom. To get this feature, call Executors.newVirtualThreadExecutor
.
Experimental builds of Project Loom are available now, based on early-access Java 17. The Loom team is asking for feedback. For more info, see recent presentations and interviews by Ron Pressler of Oracle.
System.out.println( "INFO - executor service about to start. " + Instant.now() );
try (
ExecutorService executorService = Executors.newVirtualThreadExecutor() ;
)
{
for ( int i = 0 ; i < 7 ; i++ )
{
executorService.submit( ( ) -> System.out.println( Instant.now() ) );
}
}
// Notice that when reaching this point we block until all submitted tasks still running are fin
// because that is the new behavior of `ExecutorService` being `AutoCloseable`.
System.out.println( "INFO - executor service shut down at this point. " + Instant.now() );
When run.
INFO - executor service about to start. 2021-02-08T06:27:03.500093Z
2021-02-08T06:27:03.554440Z
2021-02-08T06:27:03.554517Z
2021-02-08T06:27:03.554682Z
2021-02-08T06:27:03.554837Z
2021-02-08T06:27:03.555015Z
2021-02-08T06:27:03.555073Z
2021-02-08T06:27:03.556675Z
INFO - executor service shut down at this point. 2021-02-08T06:27:03.560723Z
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. UseawaitTermination
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
InterruptedExceptionBlocks 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()
.
How to wait for all tasks in an ThreadPoolExecutor to finish without shutting down the Executor?
If you are interested in knowing when a certain task completes, or a certain batch of tasks, you may use ExecutorService.submit(Runnable)
. Invoking this method returns a Future
object which may be placed into a Collection
which your main thread will then iterate over calling Future.get()
for each one. This will cause your main thread to halt execution until the ExecutorService
has processed all of the Runnable
tasks.
Collection<Future<?>> futures = new LinkedList<Future<?>>();
futures.add(executorService.submit(myRunnable));
for (Future<?> future:futures) {
future.get();
}
How to correctly implement executor that runs multiple iterations and waits for all tasks to complete and successfully terminates after tasks are done
With reference to ThreadPoolExecutor documentation. The awaitTermination() method description reads:
Blocks until all tasks have completed execution after a shutdown request
While the shutdown() method descriptin reads
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted
Which indicates that awaitTermination() call is effective after a shutdown() call.
To solve the above problem, shutdown() needs to be called first and then awaitTermination()
NOTE: I have not personally tested this; however, John has, as mentioned in the comment of the original post and the mechanism works
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 bysubmit()
and callget()
on everyFuture
instance - after calling
shutdown
onservice
callawaitTermination
onservice
until it returnstrue
- instead of calling
submit
onservice
add yourRunnable
instances to ajava.util.List
and pass this list to theinvokeAll
method called onservice
Related Topics
Sorting a Collection of Objects
Calling a Subclass Method from Superclass
Why Does Inetaddress.Isreachable Return False, When I Can Ping the Ip Address
Avoid Jackson Serialization on Non Fetched Lazy Objects
How to Catch an Exception from a Thread
What Is the Exact Meaning of Static Fields in Java
Parse String to Date with Different Format in Java
In Java, How to Convert a Byte Array to a String of Hex Digits While Keeping Leading Zeros
How to Generate Uml Diagrams (Especially Sequence Diagrams) from Java Code
Unrecognized Ssl Message, Plaintext Connection? Exception
How to Import a Class from Default Package
"Code Too Large" Compilation Error in Java
Best Way to List Files in Java, Sorted by Date Modified