CyclicBarrier

A CyclicBarrier is like a rendezvous point for threads. All threads need to reach certain point(barrier) before they can continue.

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;

public class Main {

    public static void main(String[] args) {

        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("All threads have reached the barrier");
        });

        Runnable task = () -> {
            String name = Thread.currentThread().getName();
            try {
                System.out.println(name + " is performing task 1.");
                Thread.sleep(1000);
                // signal that current task have passed the barrier and wait for others
                barrier.await();
                System.out.println(name + " has passed the first barrier. starting task 2");
                Thread.sleep(1000);
                barrier.await();
                System.out.println(name + " has passed the second barrier.");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        };

        new Thread(task).start();
        new Thread(task).start();
        new Thread(task).start();
    }
}

Expected output:

Thread-0 is performing task 1.
Thread-1 is performing task 1.
Thread-2 is performing task 1.
All threads have reached the barrier
Thread-1 has passed the first barrier. starting task 2
Thread-2 has passed the first barrier. starting task 2
Thread-0 has passed the first barrier. starting task 2
All threads have reached the barrier
Thread-0 has passed the second barrier.
Thread-1 has passed the second barrier.
Thread-2 has passed the second barrier.