Open In App

CyclicBarrier in Java with Examples

Last Updated : 07 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Java CyclicBarrier is used to make threads wait for each other. It is used when different threads process a part of the computation, and when all threads have completed the execution, the result needs to be combined in the parent thread. In other words, a CyclicBarrier is used when multiple threads carry out different sub-tasks and the output of these sub-tasks needs to be combined to form the final output. After completing its execution, threads call the await() method and waits for other threads to reach the barrier. Once all the threads have reached the barriers, then give the way for the threads to proceed.

Working of CyclicBarrier

CyclicBarriers are defined in java.util.concurrent package. First, a new instance of a CyclicBarrier is created specifying the number of threads that the barrier should wait upon.

CyclicBarrier newBarrier = new CyclicBarrier(numberOfThreads);

Each thread does some computation, and after completing its execution, it calls the await() method as shown below:

public void run() {

// thread does the computation

newBarrier.await();

}


The image below demonstrates the Working of the Cyclic Barrier


Once all the threads that called await() reach the barrier and the total count equals the specified number of threads then the barrier will allow the threads to continue. The CyclicBarrier can be set up with an action that runs after all threads have reached the barrier. This action can be used to combine or make use of the results from the threads waiting at the barrier.

Runnable action = ... // action to be performed when all threads reach the barrier;

CyclicBarrier newBarrier = new CyclicBarrier(numberOfThreads, action);


Methods of CyclicBarrier

Now, we are going to discuss the methods of CyclicBarrier in Java

1. getParties(): This method returns the number of parties requires to trip this barrier.

Syntax:

public int getParties()

Return Type: Returns the number of parties required to trip this barrier.


2. reset(): This method resets the barrier to its initial state.

Syntax:

public void reset()

Return Type: void but resets the barrier to its initial state. If any parties are currently waiting at the barrier, they will return with a BrokenBarrierException.


3. isBroken(): This method queries if this barrier is in a broken state.

Syntax:

public boolean isBroken()

Return Type: Returns true if one or more parties broke out of this barrier due to interruption or timeout since construction or the last reset, or a barrier action failed due to an exception; false otherwise.


4. getNumberWaiting(): This method returns the number of parties currently waiting at the barrier.

Syntax:

public int getNumberWaiting()

Return Type: Returns the number of parties currently blocked in await().


5. await(): This method Waits until all parties have invoked await on this barrier.

Syntax:

public int await() throws InterruptedException, BrokenBarrierException

Return Type: Return the arrival index of the current thread, where index getParties() - 1 indicates the first to arrive and zero indicates the last to arrive.


6. await(long timeout, TimeUnit unit): This method waits until all parties have invoked await() on this barrier, or the specified waiting time elapses.

Syntax:

public int await(long timeout, TimeUnit unit)

throws InterruptedException, BrokenBarrierException, TimeoutException

Return Type: Return the arrival index of the current thread, where index getParties() - 1 indicates the first to arrive and zero indicates the last to arrive.


Program to Demonstrate Execution on CyclicBarrier

Java
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

class Computation1 implements Runnable {
    public static int product = 0;

    public void run() {
        product = 2 * 3;
        try {
            Tester.newBarrier.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

class Computation2 implements Runnable {
    public static int sum = 0;

    public void run() {
        // check if newBarrier is broken or not
        System.out.println("Is the barrier broken? - " + Tester.newBarrier.isBroken());
        sum = 10 + 20;
        try {
            Tester.newBarrier.await(3000, TimeUnit.MILLISECONDS);
            // number of parties waiting at the barrier
            System.out.println("Number of parties waiting at the barrier at this point = " + Tester.newBarrier.getNumberWaiting());
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

public class Tester implements Runnable {
    public static CyclicBarrier newBarrier = new CyclicBarrier(3);

    public static void main(String[] args) {
        // parent thread
        Tester test = new Tester();
        Thread t1 = new Thread(test);
        t1.start();
    }

    public void run() {
        System.out.println("Number of parties required to trip the barrier = " + newBarrier.getParties());
        System.out.println("Sum of product and sum = " + (Computation1.product + Computation2.sum));

        // objects on which the child thread has to run
        Computation1 comp1 = new Computation1();
        Computation2 comp2 = new Computation2();

        // creation of child threads
        Thread t1 = new Thread(comp1);
        Thread t2 = new Thread(comp2);

        // moving child threads to runnable state
        t1.start();
        t2.start();

        try {
            Tester.newBarrier.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }

        // barrier breaks as the number of threads waiting for the barrier
        // at this point = 3
        System.out.println("Sum of product and sum = " + (Computation1.product + Computation2.sum));

        // Resetting the newBarrier
        newBarrier.reset();
        System.out.println("Barrier reset successful");
    }
}

Output:

Output

Explanation: The value of (sum + product) = 0 is printed on the console because the child thread have not yet run to set the values of sum and product variable. Following this, (sum + product) = 36 is printed on the console because the child threads ran setting the values of sum and product. Furthermore, the number of waiting thread on the barrier reached 3, due to which the barrier then allowed all thread to pass and finally 36 was printed. The value of "Number of parties waiting at the barrier at this point" = 0 because all the three threads had already called await() method and hence, the barrier is no longer active. In the end, newBarrier is reset and can be used again.


BrokenBarrierException

A barrier breaks when any of the waiting thread leaves the barrier. This happens when one or more waiting thread is interrupted or when the waiting time is completed because the thread called the await() methods with a timeout as follows:

newBarrier.await(1000, TimeUnit.MILLISECONDS);

This method waits for a maximum of 1000 milliseconds. If the barrier is broken because one or more threads didn't reach it, all the other threads waiting at the barrier will get a BrokenBarrierException when they call await(). The threads that are already waiting will have their await() call stopped.


CyclicBarrier vs CountDownLatch

The table below demonstrates the difference between CyclicBarrier and a CountDownLatch

Features

CyclicBarrier

CountDownLatch

Reusability

It can be used multiple times.

It can only be used once.

Scenarios

Suitable for scenarios where you need to coordinate multiple phases of computation.

Suitable for scenarios where you need to wait for a set of events to complete just once.


Next Article
Practice Tags :

Similar Reads