CyclicBarrier in Java with Real Time Example - Java @ Desk

Saturday, December 15, 2018

CyclicBarrier in Java with Real Time Example

CyclicBarrier in Java with Real Time Example

CyclicBarrier is a thread syncronization mechanism in which all the threads are requested to wait at a certain point, before all of them move forward. The specific point is called a barrier and threads enter into a wait state at barrier point until all working threads reaches at that point. Once all threads reaches barrier point, they are allowed to continue.

The importance of a Cyclic Barrier is that it is cyclic i.e. once all the threads reaches barrier point and resumes their individual jobs, CyclicBarrier is allowed to reset.

Here is an example of a Cricket Match. Before a bowler is allowed to bowl first delivery, it waits for 2 umpires to reach their specific positions and all 10 fielders at their respective fielding positions. Until and unless 2 umpires and 11 fielders reaches at their respective positions, no thread can move forward. For example, even if 2 umpires and 10 fielders reach their points, they still need to wait for 11th player to reach to his position. Once 11th player reaches his position and calls await() method, bowler is allowed to bowl.

Here is a real time implementation of CyclicBarrier

CyclicBarrierCricket.java - This is a main class that initializes CyclicBarrier. It initializes threads for 11 Players and 2 Umpires and then calls the await method(). As soon as both the umpires and 11 players calls await(), this thread moves forward.
package com.cyclicbarrier.learning;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierCricket {

 public static void main(String args[]) {
  CyclicBarrier barrier = new CyclicBarrier(14);
  System.out.println("Match about to Start");

  System.out.println("Initializing Umpires");

  for (int i = 1; i <= 2; i++) {
   CyclicBarrierUmpire barrierUmpire = new CyclicBarrierUmpire();
   barrierUmpire.setUmpireNumber(i);
   barrierUmpire.setCyclicBarrier(barrier);
   Thread thread = new Thread(barrierUmpire);
   thread.start();
  }

  System.out.println("Umpires Thread Started");

  System.out.println("Initializing Players");

  for (int i = 1; i <= 11; i++) {
   CyclicBarrierPlayers cyclicBarrierPlayers = new CyclicBarrierPlayers();
   cyclicBarrierPlayers.setPlayerNumber(i);
   cyclicBarrierPlayers.setCyclicBarrier(barrier);
   Thread thread = new Thread(cyclicBarrierPlayers);
   thread.start();
  }

  System.out.println("Players Thread Started");
  
        try {
   barrier.await();
  } catch (InterruptedException | BrokenBarrierException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

        System.out.println("Players and Umpires all set at their respective Positions. Lets start a Game");
 }

}


CyclicBarrierUmpire.java - This is a Java thread to initialize both the umpires. Both the umpires calls the await() method to notify that we are all set and waiting for rest of the players to move to the position.
package com.cyclicbarrier.learning;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierUmpire implements Runnable {

    private CyclicBarrier cyclicBarrier;
    
    private int umpireNumber;
 
 @Override
 public void run() {
  System.out.println("Umpire " + umpireNumber + " Moving to Position");
        try {
   Thread.sleep(3000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  System.out.println("Umpire " + umpireNumber + " Set at Position");
  
        try {
   cyclicBarrier.await();
  } catch (InterruptedException | BrokenBarrierException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
        System.out.println("Umpire - " + umpireNumber + " all set");
 
  
 }

 public int getUmpireNumber() {
  return umpireNumber;
 }

 public void setUmpireNumber(int umpireNumber) {
  this.umpireNumber = umpireNumber;
 }

 public CyclicBarrier getCyclicBarrier() {
  return cyclicBarrier;
 }

 public void setCyclicBarrier(CyclicBarrier cyclicBarrier) {
  this.cyclicBarrier = cyclicBarrier;
 }
 
}


CyclicBarrierPlayers.java - This is a Java thread to initialize all the players. All 11 players calls the await() method to notify that we are all set and waiting for rest of the players to move to the position. As soon as 11th player calls await() method, main class moves forward and allows a match to start.
package com.cyclicbarrier.learning;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierPlayers implements Runnable {

    private CyclicBarrier cyclicBarrier;
    
    private int playerNumber;
 
 @Override
 public void run() {
  System.out.println("Player " + playerNumber + " Moving to Fielding Position");
        try {
   Thread.sleep(3000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  System.out.println("Player " + playerNumber + " Fielding Position Set");
  
        try {
   cyclicBarrier.await();
  } catch (InterruptedException | BrokenBarrierException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
        System.out.println("Player - " + playerNumber + " all set");
 }

 public CyclicBarrier getCyclicBarrier() {
  return cyclicBarrier;
 }

 public void setCyclicBarrier(CyclicBarrier cyclicBarrier) {
  this.cyclicBarrier = cyclicBarrier;
 }

 public int getPlayerNumber() {
  return playerNumber;
 }

 public void setPlayerNumber(int playerNumber) {
  this.playerNumber = playerNumber;
 }
 
}


Output -
Match about to Start
Initializing Umpires
Umpires Thread Started
Initializing Players
Umpire 1 Moving to Position
Umpire 2 Moving to Position
Player 1 Moving to Fielding Position
Player 2 Moving to Fielding Position
Player 3 Moving to Fielding Position
Player 4 Moving to Fielding Position
Player 5 Moving to Fielding Position
Player 6 Moving to Fielding Position
Player 7 Moving to Fielding Position
Player 8 Moving to Fielding Position
Player 9 Moving to Fielding Position
Players Thread Started
Player 10 Moving to Fielding Position
Player 11 Moving to Fielding Position
Umpire 1 Set at Position
Umpire 2 Set at Position
Player 1 Fielding Position Set
Player 4 Fielding Position Set
Player 5 Fielding Position Set
Player 8 Fielding Position Set
Player 3 Fielding Position Set
Player 2 Fielding Position Set
Player 9 Fielding Position Set
Player 7 Fielding Position Set
Player 6 Fielding Position Set
Player 11 Fielding Position Set
Player 10 Fielding Position Set
Player - 10 all set
Umpire - 1 all set
Players and Umpires all set at their respective Positions. Lets start a Game
Umpire - 2 all set
Player - 1 all set
Player - 5 all set
Player - 4 all set
Player - 8 all set
Player - 7 all set
Player - 9 all set
Player - 6 all set
Player - 11 all set
Player - 2 all set
Player - 3 all set


Its clearly visible, main client prints "Players and Umpires all set at their respective Positions. Lets start a Game" only when all the Umpire and Player threads have called the await() method. Till then it was in wait state.





No comments:

Post a Comment