CountDownLatch
The main thread initializes a CountDownLatch, e.g.:
CountDownLatch countDownLatch = new CountDownLatch(3);
It passes countDownLatch to n (in this example 3) sub-threads, for instance via constructor.
Finally, the main thread waits for the execution of the sub threads:
countDownLatch.await();
Once ready, every thread finally calls
countDownLatch.countDown();
Every countDown() call decrements the initial number, and the main thread finally will resume with the operations defined after the wait() statement.
See more here: https://howtodoinjava.com/java/multi-threading/when-to-use-countdownlatch-java-concurrency-example-tutorial/