Example 23.14 illustrates using a single cyclic barrier that is shared by three threads. The barrier is declared at (2), requiring three parties and having the barrier action at (1) being performed when the barrier is tripped. The task declared at (3) calls the await() method on the barrier when it wants to synchronize on the barrier. Note the checked exceptions that can be thrown by the await() method. The threads are created and started at (4).

The output from Example 23.14 shows that each thread waited at the barrier point and announced it was released after the barrier tripped. The barrier action is performed by thread T2 that was the last one to arrive at the barrier point.

Example 23.14 Cyclic Barrier

Click here to view code image

package synchronizers;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
  public static final int PARTIES = 3;
  public static void main(String args[]) {
    Runnable barrierAction =  () ->                                        // (1)
          System.out.println(“Barrier action by “
                             + Thread.currentThread().getName()
                             + “: All tasks are released.”);
    CyclicBarrier barrier = new CyclicBarrier(PARTIES, barrierAction);     // (2)
    Runnable task = () -> {                                                // (3)
      String threadName = Thread.currentThread().getName();
      try {
        System.out.println(threadName + ” is now waiting”);
        barrier.await();                                        // Barrier point.
        System.out.println(threadName + ” is now released”);
      } catch (BrokenBarrierException | InterruptedException e) {
        e.printStackTrace();
      }
    };
    for (int i = 0; i < PARTIES; i++) {                                    // (4)
      new Thread(task, “T” + (i+1)).start();
    }
  }
}

Probable output from the program:

Click here to view code image

T1 is now waiting
T3 is now waiting
T2 is now waiting
Barrier action by T2: All tasks are released.
T2 is now released
T1 is now released
T3 is now released

Threads can of course share more than one barrier, having a different number of parties and different barrier actions.

Once a barrier is tripped, its thread wait count is reset to zero, and the barrier can be used again to implement a barrier point by calling the await() method.

If more threads than the required number invoke the await() method, then the required number of threads will cause the barrier to trip. This will allow the required number to continue and will reset the wait count, and the extra threads will have to wait for the barrier to trip again.

The cyclic barrier implements the all-or-none model. Either all waiting threads successfully continue execution past the await() method, or none do. If one thread waiting at a barrier point leaves prematurely—which could be due to an interruption, timeout, or failure—then all other waiting threads also leave abnormally via the checked java.util.concurrent.BrokenBarrierException. In this case, the barrier is said to be broken. The method isBroken() can be used to determine whether this is the case. A broken barrier can be reset and reused.