CountDownLatch, we create a
CountDownLatch with the number of tasks to execute. After a task is completed, we use
countDown to signal that. The main thread uses
await to wait for all tasks to finish.
Here we manually create the threads, you can also use
CompletableFuture, we use
supplyAsync to create new
CompletableFutures, then use
allOf to create a new
CompletableFuture which is completed when all the provided
CompletableFutures are completed.
See GitHub for the complete source code.