Cyclic Barrier

There might be situation where we might have to trigger event only when one or more threads completes certain operation.A cyclic barrier is a thread-synchronization construct that lets a set of threads wait for each other to reach a common barrier point.
The barrier is called cyclic because it can be re-used after the waiting threads are released.

CyclicBarrier has 2 Constructor :

  • CyclicBarrier(int parties):New CyclicBarrier is created where parties number of thread wait for each other to reach common barrier point, when all threads have reached common barrier point, parties number of waiting threads are released.
  • CyclicBarrier(int parties, Runnable barrierAction):New CyclicBarrier is created where parties number of thread wait for each other to reach common barrier point, when all threads have reached common barrier point, parties number of waiting threads are released and barrierAction (event) is triggered.

Either constructor throws java.lang.IllegalArgumentException when the value passed to nthreads is less than 1.

CyclicBarrier declares an int await() method that typically causes the calling thread to wait unless the thread is the final thread. If so, and if a nonnull Runnable was passed to barrierAction, the final thread executes the runnable before the other threads continue.

await() throws InterruptedException when the thread that invoked this method is interrupted while waiting. This method throws BrokenBarrierException when another thread was interrupted while the invoking thread was waiting, the barrier was broken when await() was called, or the barrier action (when present) failed because an exception was thrown from the runnable's run() method.

Lets see an program to make the concept more clear:

CyclicBarrierMain.java
public class CyclicBarrierMain {

    public static void main(String args[]) {

        CombineIndividualTask combineIndividualTask = new CombineIndividualTask();
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3, combineIndividualTask);

        Thread subtaskOne = new Thread(new Task(cyclicBarrier), "SubtaskOne");
        Thread subtaskTwo = new Thread(new Task(cyclicBarrier), "SubtaskTwo");
        Thread subtaskThree = new Thread(new Task(cyclicBarrier), "SubtaskThree");

        subtaskOne.start();
        subtaskTwo.start();
        subtaskThree.start();

    }
}

Task.java
public class Task implements Runnable {

    private CyclicBarrier cyclicBarrier;

    public Task(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " is waiting on barrier");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

CombineIndividualTask.java
public class CombineIndividualTask implements Runnable {

    @Override
    public void run() {
        //this task will be executed once all the subtask complete
        System.out.println("All subtask completed there work , lets combine");
    }

}

Output:
SubtaskTwo is waiting on barrier
SubtaskOne is waiting on barrier
SubtaskThree is waiting on barrier
All subtask completed there work , lets combine
SubtaskOne has crossed the barrier
SubtaskThree has crossed the barrier
SubtaskTwo has crossed the barrier

As per out it seems clear that initially all the threads wait for each other untill all the othem reach to the cyclicbarrier point . Once all the thread reach to the cyclic barrier point an event(runnable objetc) is being executed.

Real life applications of CyclicBarrier :
  • Cyclic barriers can be used to perform lengthy calculations by breaking them into smaller individual tasks (as demonstrated by CyclicBarrier's Javadoc example code).
  • Cyclic barriers are also used in multiplayer games that cannot start until the last player has joined. 

Why barrier is called Cyclic in java?

The barrier is called cyclic because CyclicBarrier can be reused after -
All the waiting threads are released and 
event has been triggered. 

In our above example if we modify the code as below, then the same cyclic barrier will be used :
Thread subtaskOne = new Thread(new Task(cyclicBarrier), "SubtaskOne");
        Thread subtaskTwo = new Thread(new Task(cyclicBarrier), "SubtaskTwo");
        Thread subtaskThree = new Thread(new Task(cyclicBarrier), "SubtaskThree");

        subtaskOne.start();
        subtaskTwo.start();
        subtaskThree.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("\n Cyclic Barrier is being used again :\n ");

        Thread subtaskFour = new Thread(new Task(cyclicBarrier), "SubtaskFour");
        Thread subtaskFive = new Thread(new Task(cyclicBarrier), "SubtaskFive");
        Thread subtaskSix = new Thread(new Task(cyclicBarrier), "SubtaskSix");

        subtaskFour.start();
        subtaskFive.start();
        subtaskSix.start();

Output:
SubtaskThree is waiting on barrier
SubtaskTwo is waiting on barrier
SubtaskOne is waiting on barrier
All subtask completed there work , lets combine
SubtaskOne has crossed the barrier
SubtaskTwo has crossed the barrier
SubtaskThree has crossed the barrier

Cyclic Barrier is being used again :
 
SubtaskFour is waiting on barrier
SubtaskSix is waiting on barrier
SubtaskFive is waiting on barrier
All subtask completed there work , lets combine
SubtaskFive has crossed the barrier
SubtaskFour has crossed the barrier
SubtaskSix has crossed the barrier

As per the above output we can see that same cyclic barrier has been used again.


This covers the concept of cyclic barrier in Java Concurrency . if you have any doubt or you want to add anything then please comment below .

Comments

Popular posts from this blog

Deploy standalone Spring MVC Application in Docker Container

Refactor Code : Separate Query from Modifier

ConcurrentHashMap Internal Working