What is the simplest way to to wait for all tasks of ExecutorService to finish? My task is primarily computational, so I just want to run a large number of jobs
Root cause for IllegalMonitorStateException:
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
From your code, you have just called wait() on ExecutorService without owning the lock.
Below code will fix IllegalMonitorStateException
try
{
synchronized(es){
es.wait(); // Add some condition before you call wait()
}
}
Follow one of below approaches to wait for completion of all tasks, which have been submitted to ExecutorService.
Iterate through all Future tasks from submit on ExecutorService and check the status with blocking call get() on Future object
Using invokeAll on ExecutorService
Using CountDownLatch
Using ForkJoinPool or newWorkStealingPool of Executors(since java 8)
Shutdown the pool as recommended in oracle documentation page
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();
}
If you want to gracefully wait for all tasks for completion when you are using option 5 instead of options 1 to 4, change
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
to
a while(condition) which checks for every 1 minute.