Implementation of custom/own CyclicBarrier in java - Detailed explanation with full program


Contents of page :
  • Custom CyclicBarrier?
  • Custom CyclicBarrier’s  constructor >
  • CyclicBarrierCustom(int parties, Runnable barrierAction)
  • CODE >
  • Custom CyclicBarrier’s await() method :
  • int await() throws InterruptedException
  • CODE >
  • Custom CyclicBarrier’s code >
  • Program to demonstrate usage of Custom CyclicBarrier >
  • Let’s discuss output in detail, to get better understanding of Custom CyclicBarrier usage in program >
  • Why barrier is called Cyclic?

Custom CyclicBarrier?
In previous tutorial we read how to use CyclicBarrier in thread concurrency in java. In this post we will be implementing custom CyclicBarrier. This post intends you give you basic functionality of CyclicBarrier using your own java code

There might be situation where we might have to trigger event only when one or more threads completes certain operation.

2 or more threads wait for each other to reach a common barrier point. When all threads have reached common barrier point (i.e. when all threads have called await() method) >
  • All waiting threads are released, and
  • Event can be triggered as well.


Custom CyclicBarrier’s  constructor >
  • CyclicBarrierCustom(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.

CODE >
   public CyclicBarrierCustom(int parties, Runnable cyclicBarrrierEvent) {
          initialParties=parties;
          partiesAwait=parties;  
          this.cyclicBarrrierEvent=cyclicBarrrierEvent;
   }


Custom CyclicBarrier’s await() method :
  • int await() throws InterruptedException
If the current thread is not the last to arrive(i.e. call await() method) then it waits until one of the following things happens -
  • The last thread to call arrive(i,.e. call await() method), or
  • Some other thread interrupts the current thread, or
  • Some other thread interrupts one of the other waiting threads, or
  • Some other thread times out while waiting for barrier, or
  • Some other thread invokes reset() method on this cyclicBarrier.

CODE >
  public synchronized void await() throws InterruptedException {
      //decrements awaiting parties by 1.
      partiesAwait--;
         
      //If the current thread is not the last to arrive, thread will wait.
      if(partiesAwait>0){
             this.wait();
      }
      /*If the current thread is last to arrive, notify all waiting threads, and
      launch event*/
      else{
             /* All parties have arrive, make partiesAwait equal to initialParties,
              so that CyclicBarrier could become cyclic. */
             partiesAwait=initialParties;
             
             notifyAll(); //notify all waiting threads
                
             cyclicBarrrierEvent.run(); //launch event
      }
}



Custom CyclicBarrier’s code >
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
/**
* @author AnkitMittal
* Copyright (c), AnkitMittal .
* All Contents are copyrighted and must not be reproduced in any form.
   2 or more threads wait for each other to reach a common barrier point.
   When all threads have reached common barrier point (i.e. when all
   threads have called await() method) >
          - All waiting threads are released, and
          - Event can be triggered as well.
*/
class CyclicBarrierCustom{
 
   int initialParties; //total parties
   int partiesAwait; //parties yet to arrive
Runnable cyclicBarrrierEvent;
  
   /**
   * 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.
   */
   public CyclicBarrierCustom(int parties, Runnable cyclicBarrrierEvent) {
          initialParties=parties;
          partiesAwait=parties;  
          this.cyclicBarrrierEvent=cyclicBarrrierEvent;
   }
   /**
   * If the current thread is not the last to arrive(i.e. call await() method) then
   it waits until one of the following things happens -
                 - The last thread to call arrive(i,.e. call await() method), or
                 - Some other thread interrupts the current thread, or
                 - Some other thread interrupts one of the other waiting threads, or
                 - Some other thread times out while waiting for barrier, or
                 - Some other thread invokes reset() method on this cyclicBarrier.
   */
   public synchronized void await() throws InterruptedException {
          //decrements awaiting parties by 1.
          partiesAwait--;
         
          //If the current thread is not the last to arrive, thread will wait.
          if(partiesAwait>0){
                 this.wait();
          }
          /*If the current thread is last to arrive, notify all waiting threads, and
          launch event*/
          else{
                 /* All parties have arrive, make partiesAwait equal to initialParties,
                  so that CyclicBarrier could become cyclic. */
                 partiesAwait=initialParties;
                
                 notifyAll(); //notify all waiting threads
                
                 cyclicBarrrierEvent.run(); //launch event
          }
   }
}

Program to demonstrate usage of Custom CyclicBarrier >
/**
* @author AnkitMittal
* Copyright (c), AnkitMittal .
* All Contents are copyrighted and must not be reproduced in any form.
   2 or more threads wait for each other to reach a common barrier point.
   When all threads have reached common barrier point (i.e. when all
   threads have called await() method) >
          - All waiting threads are released, and
          - Event can be triggered as well.
*/
class CyclicBarrierCustom{
 
   int initialParties; //total parties
   int partiesAwait; //parties yet to arrive
Runnable cyclicBarrrierEvent;
  
   /**
   * 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.
   */
   public CyclicBarrierCustom(int parties, Runnable cyclicBarrrierEvent) {
          initialParties=parties;
          partiesAwait=parties;  
          this.cyclicBarrrierEvent=cyclicBarrrierEvent;
   }
   /**
   * If the current thread is not the last to arrive(i.e. call await() method) then
   it waits until one of the following things happens -
                 - The last thread to call arrive(i,.e. call await() method), or
                 - Some other thread interrupts the current thread, or
                 - Some other thread interrupts one of the other waiting threads, or
                 - Some other thread times out while waiting for barrier, or
                 - Some other thread invokes reset() method on this cyclicBarrier.
   */
   public synchronized void await() throws InterruptedException {
          //decrements awaiting parties by 1.
          partiesAwait--;
         
          //If the current thread is not the last to arrive, thread will wait.
          if(partiesAwait>0){
                 this.wait();
          }
          /*If the current thread is last to arrive, notify all waiting threads, and
          launch event*/
          else{
                 /* All parties have arrive, make partiesAwait equal to initialParties,
                  so that CyclicBarrier could become cyclic. */
                 partiesAwait=initialParties;
                
                 notifyAll(); //notify all waiting threads
                
                 cyclicBarrrierEvent.run(); //launch event
          }
   }
}


/**
* Main class
*/
public class CyclicBarrierCustomTest {
   public static void main(String[] args) {
          /*
          * Create CountDownLatch with 3 parties, when all 3 parties
          * will reach common barrier point CyclicBarrrierEvent will be
          * triggered i.e. run() method of CyclicBarrrierEvent will be called
          */
          CyclicBarrierCustom cyclicBarrierCustom=new CyclicBarrierCustom(3 ,new CyclicBarrrierEvent());
          System.out.println("CountDownLatch has been created with parties=3,"
                       + " when all 3 parties will reach common barrier point "
                       + "CyclicBarrrierEvent will be triggered");
          MyRunnable myRunnable1=new MyRunnable(cyclicBarrierCustom);
         
          //Create and start 3 threads
          new Thread(myRunnable1,"Thread-1").start();
          new Thread(myRunnable1,"Thread-2").start();
          new Thread(myRunnable1,"Thread-3").start();
  
         
         
   }
}




class MyRunnable implements Runnable{
   CyclicBarrierCustom cyclicBarrierCustom;
  
   MyRunnable(CyclicBarrierCustom cyclicBarrierCustom){
          this.cyclicBarrierCustom=cyclicBarrierCustom;
   }
  
   @Override
   public void run() {
         
          System.out.println(Thread.currentThread().getName() +
                       " is waiting for all other threads to reach common barrier point");
          try {
                 Thread.sleep(1000);
                 /*
                 * when all 3 parties will call await() method (i.e. common barrier point)
                 * CyclicBarrrierEvent will be triggered and all waiting threads will
                 * be released.
                 */
                 cyclicBarrierCustom.await();
          } catch (InterruptedException e) {
                 e.printStackTrace();
          }
          System.out.println("As all threads have reached common barrier point "
                       + Thread.currentThread().getName() +
                       " has been released");
   }
  
}


class CyclicBarrrierEvent implements Runnable{
   public void run() {
          System.out.println("As all threads have reached common barrier point "
                       + ", CyclicBarrrierEvent has been triggered");
   }
  
}
/*OUTPUT
CountDownLatch has been created with parties=3, when all 3 parties will reach common barrier point CyclicBarrrierEvent will be triggered
Thread-1 is waiting for all other threads to reach common barrier point
Thread-2 is waiting for all other threads to reach common barrier point
Thread-3 is waiting for all other threads to reach common barrier point
As all threads have reached common barrier point , CyclicBarrrierEvent has been triggered
As all threads have reached common barrier point Thread-1 has been released
As all threads have reached common barrier point Thread-3 has been released
As all threads have reached common barrier point Thread-2 has been released
*/

Let’s discuss output in detail, to get better understanding of Custom CyclicBarrier usage in program >

Note : I have mentioned output in green text.


CountDownLatch has been created with parties=3, when all 3 parties will reach common
barrier point CyclicBarrrierEvent will be triggered
custom CountDownLatch has been created with parties=3, when Thread-1, Thread-2 and Thread-3 will call await() method, CyclicBarrrierEvent will be triggered

Thread-1 is waiting for all other threads to reach common barrier point
Thread-1 has called await(), it is waiting for Thread-2 and Thread-3 to call await() method

Thread-2 is waiting for all other threads to reach common barrier point
Thread-1 and Thread-2 has called await(), and they are waiting for Thread-3 to call await() method

Thread-3 is waiting for all other threads to reach common barrier point
Thread-1, Thread-2, and Thread-3 has called await().


As all threads have reached common barrier point , CyclicBarrrierEvent has been triggered
As Thread-1, Thread-2, and Thread-3 has called await(). So, CyclicBarrrierEvent is triggered  i.e. run() method of CyclicBarrrierEvent is called

As all threads have reached common barrier point Thread-1 has been released
As all threads have reached common barrier point Thread-3 has been released
As all threads have reached common barrier point Thread-2 has been released
As Thread-1, Thread-2, and Thread-3 has called await(), all waiting threads are released and completes there execution.


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

When we execute 3 more threads in above program CyclicBarrrierEvent will be triggered again.

             
//Create and start 3 threads
new Thread(myRunnable1,"Thread-1").start();
new Thread(myRunnable1,"Thread-2").start();
new Thread(myRunnable1,"Thread-3").start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Create and start 3 more threads
new Thread(myRunnable1,"Thread-4").start();
new Thread(myRunnable1,"Thread-5").start();
new Thread(myRunnable1,"Thread-6").start();

Output will be -

/*OUTPUT
CountDownLatch has been created with parties=3, when all 3 parties will reach common barrier point CyclicBarrrierEvent will be triggered
Thread-1 is waiting for all other threads to reach common barrier point
Thread-2 is waiting for all other threads to reach common barrier point
Thread-3 is waiting for all other threads to reach common barrier point
As all threads have reached common barrier point , CyclicBarrrierEvent has been triggered
As all threads have reached common barrier point Thread-3 has been released
As all threads have reached common barrier point Thread-2 has been released
As all threads have reached common barrier point Thread-1 has been released


Thread-4 is waiting for all other threads to reach common barrier point
Thread-5 is waiting for all other threads to reach common barrier point
Thread-6 is waiting for all other threads to reach common barrier point
As all threads have reached common barrier point , CyclicBarrrierEvent has been triggered
As all threads have reached common barrier point Thread-6 has been released
As all threads have reached common barrier point Thread-4 has been released
As all threads have reached common barrier point Thread-5 has been released
*/


In previous tutorial we read how to use CyclicBarrier in thread concurrency in java. In this post we implement your own/custom CyclicBarrier. This post gave you basic functionality of CyclicBarrier using your own java code



Having any doubt? or you you liked the tutorial! Please comment in below section.
Please express your love by liking JavaMadeSoEasy.com (JMSE) on facebook, following on google+ or Twitter.



RELATED LINKS>

java.util.concurrent.CountDownLatch >

java.util.concurrent.CountDownLatch in java

Implementation of custom/own CountDownLatch in java



java.util.concurrent.CyclicBarrier >

CyclicBarrier in java



Thread concurrency Interviews >

No comments:

Post a Comment