CyclicBarrier in Java


CyclicBarrier Java MultithreadingViews 1314

This tutorial will help you understand CyclicBarrier in Java which is a concurrent utility along with an example.

Java CyclicBarrier

CyclicBarrier is a synchronization technique that is part of the java.util.concurrent package and is available from Java5. A CyclicBarrier waits for all threads to complete its execution before reaching a point. This point is the barrier that ensures all the threads complete their execution before reaching here. In other words, each thread may perform a subtask and finally ensures that the parent thread combines the result of all these subtasks. After the threads complete their execution, they wait for each other by calling the await() method.

Working of a CyclicBarrier

We can create a CyclicBarrier by specifying the number of threads in the constructor. This denotes how many threads need to wait for the barrier. Every thread invokes the await() method after completing its execution.

CyclicBarrier cb = new CyclicBarrier(int thread_count);

It is also possible to create a CyclicBarrier by specifying some action along with the thread count. This action denotes the task that all the threads perform after reaching the barrier.

CyclicBarrier cb = new CyclicBarrier(thread_count, action);

CyclicBarrier in Java Example

Methods of Java CyclicBarrier

Below are the methods present in the CyclicBarrier class in Java.

MethodDescription
int await()Waits until all threads have reached the barrier
int await(log time, TimeUnit unit)Waits until all the threads have reached the barrier or else until the specified time period elapses
int getNumberWaiting()Returns the number of threads waiting at the barrier
int getParties()Returns the number of parties requires to reach this barrier
boolean isBroken()Returns true is the barrier is in broken state
void reset()Resets the barrier to initial state

CyclicBarrier Example

Below is an example to illustrate the working and usage of CyclicBarrier and its methods. Lets understand this example in detail.

We have 2 child threads “Thread1” and “Thread2” that initializes the values for the String variable respectively. We also have a main parent thread “MainThread” where we create a CyclicBarrier with thread count as 3.

Initially, getParties() method returns 3 since we have 3 threads waiting at the barrier. The initial values of the String variable is null since the child threads have not executed. When we invoke the start() method on the child threads, it executes the corresponding run() methods. During Thread2 execution, the getNumberWaiting() method returns 0 since there are no more threads waiting for execution.

import java.util.concurrent.*;

public class MainThread implements Runnable {

  public static CyclicBarrier cb = new CyclicBarrier(3);
  
  public static void main(String[] args) {
    MainThread mt = new MainThread();
    Thread t = new Thread(mt);
    t.start();
  }

  @Override
  public void run() {
    System.out.println("Number of parties at the barrier: " + cb.getParties());
    System.out.println("Values of String: " + Thread1.value + " " + Thread2.text);
    
    Thread1 th1 = new Thread1();
    Thread2 th2 = new Thread2();
    
    Thread t1 = new Thread(th1);
    Thread t2 = new Thread(th2);
    
    t1.start();
    t2.start();
    
    try {
      MainThread.cb.await();
    } catch (InterruptedException | BrokenBarrierException e) {
      e.printStackTrace();
    }
    
    System.out.println("Values of String: " + Thread1.value + " " + Thread2.text);
    cb.reset();
    System.out.println("CyclicBarrier reset operation");
    
  }

}

class Thread1 implements Runnable {

  public static String value;
  @Override
  public void run() {
    value = "Thread 1";
    try {
      MainThread.cb.await();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (BrokenBarrierException e) {
      e.printStackTrace();
    }
    
  }
  
}

class Thread2 implements Runnable {

  public static String text;
  @Override
  public void run() {
    System.out.println("Barrier broken: " + MainThread.cb.isBroken());
    text = "Thread 2";
    try {
      MainThread.cb.await(1000, TimeUnit.MILLISECONDS);
      System.out.println("Number of waiting threads: " + MainThread.cb.getNumberWaiting());
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (BrokenBarrierException e) {
      e.printStackTrace();
    } catch (TimeoutException e) {
      e.printStackTrace();
    }
    
  }
  
}
Number of parties at the barrier: 3
Values of String: null null
Barrier broken: false
Values of String: Thread 1 Thread 2
CyclicBarrier reset operation
Number of waiting threads: 0

Difference between CyclicBarrier and CountDownLatch

CyclicBarrierCountDownLatch
We can use CyclicBarrier multiple times after all threads have released the barrier.We can use CountDownLatch only only once till the count reaches 0
It is a synchronization technique that waits for each other to reach the barrier pointIts a synchronization technique that waits until all threads have completed the execution
It maintains thread countIt maintains task count
If 1 thread is interrupted while waiting, then other waiting threads will throw BrokenBarrierExceptionOnly current thread will throw InterruptedException and does not affect other threads.

Reference

Translate ยป