This tutorial will help you understand CyclicBarrier in Java which is a concurrent utility along with an example.
Table of Contents
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);
Methods of Java CyclicBarrier
Below are the methods present in the CyclicBarrier class in Java.
Method | Description |
---|---|
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
CyclicBarrier | CountDownLatch |
---|---|
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 point | Its a synchronization technique that waits until all threads have completed the execution |
It maintains thread count | It maintains task count |
If 1 thread is interrupted while waiting, then other waiting threads will throw BrokenBarrierException | Only current thread will throw InterruptedException and does not affect other threads. |