There are several approaches.
You can call first ExecutorService.shutdown and then ExecutorService.awaitTermination which returns:
true if this executor terminated and false if the timeout elapsed before termination
So:
There is a function called awaitTermination But a timeout has to be provided in it. Which is not a guarantee that when this returns all the tasks would have been finished. Is there a way to achieve this?
You just have to call awaitTermination in a loop.
Using awaitTermination:
A full example of this implementation:
public class WaitForAllToEnd { public static void main(String[] args) throws InterruptedException { final int total_threads = 4; ExecutorService executor = Executors.newFixedThreadPool(total_threads); for(int i = 0; i < total_threads; i++){ executor.execute(parallelWork(100 + i * 100)); } int count = 0; // This is the relevant part // Chose the delay most appropriate for your use case executor.shutdown(); while (!executor.awaitTermination(100, TimeUnit.MILLISECONDS)) { System.out.println("Waiting "+ count); count++; } } private static Runnable parallelWork(long sleepMillis) { return () -> { try { Thread.sleep(sleepMillis); } catch (InterruptedException e) { // Do Something } System.out.println("I am Thread : " + Thread.currentThread().getId()); }; } }
Using CountDownLatch:
Another option is to create a CountDownLatch with a count equal to the number of parallel tasks. Each thread calls countDownLatch.countDown();, while the main thread calls countDownLatch.await();.
A full example of this implementation:
public class WaitForAllToEnd { public static void main(String[] args) throws InterruptedException { final int total_threads = 4; CountDownLatch countDownLatch = new CountDownLatch(total_threads); ExecutorService executor = Executors.newFixedThreadPool(total_threads); for(int i = 0; i < total_threads; i++){ executor.execute(parallelWork(100 + i * 100, countDownLatch)); } countDownLatch.await(); System.out.println("Exit"); executor.shutdown(); } private static Runnable parallelWork(long sleepMillis, CountDownLatch countDownLatch) { return () -> { try { Thread.sleep(sleepMillis); } catch (InterruptedException e) { // Do Something } System.out.println("I am Thread : " + Thread.currentThread().getId()); countDownLatch.countDown(); }; } }
Using CyclicBarrier:
Another approach is to use a Cyclic Barrier
public class WaitForAllToEnd { public static void main(String[] args) throws InterruptedException, BrokenBarrierException { final int total_threads = 4; CyclicBarrier barrier = new CyclicBarrier(total_threads+ 1); ExecutorService executor = Executors.newFixedThreadPool(total_threads); for(int i = 0; i < total_threads; i++){ executor.execute(parallelWork(100 + i * 100, barrier)); } barrier.await(); System.out.println("Exit"); executor.shutdown(); } private static Runnable parallelWork(long sleepMillis, CyclicBarrier barrier) { return () -> { try { Thread.sleep(sleepMillis); } catch (InterruptedException e) { // Do Something } System.out.println("I am Thread : " + Thread.currentThread().getId()); try { barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { // Do something } }; } }
There are other approaches as well but those would require changes to your initial requirements, namely:
How to wait for all tasks to be completed when they are submitted using ExecutorService.execute() .