// Barrier2
import java.util.concurrent.*;

class Barrier2 {
  int N=4; // workers
  int Njob=2; // jobs 
  CyclicBarrier barrier; // the threading synronization 
   
  Barrier2()
  {
    System.out.println("Barrier2 constructing CyclicBarrier");

    System.out.println("master initialization");

    barrier = new CyclicBarrier(N+1); // N workers plus master
    System.out.println("start "+N+" Workers");
    for (int i=0; i<N; i++) 
      new Thread(new Worker(i)).start();
    try // required for barrier.await()
    {
      for(int job=0; job<Njob; job++)
      {
	barrier.await(); // 1a  master may run
        System.out.println("masterT1 job="+job);
        barrier = new CyclicBarrier(N+1); // N workers plus master
	barrier.await(); // 1b  master completed
        barrier = new CyclicBarrier(N+1); // N workers plus master

        barrier.await(); // 2a
        System.out.println("masterT2 job="+job);
        barrier = new CyclicBarrier(N+1); // N workers plus master
	barrier.await(); // 2b
        barrier = new CyclicBarrier(N+1); // N workers plus master
      } // end job loop 
      barrier.await(); // 3a  master finalizes
    }
    catch (InterruptedException ex)
    { 
      System.out.println("interrupted exception");
      return; 
    }
    catch (BrokenBarrierException ex)
    { 
      System.out.println("broken barrier exception");
      return; 
    } // end try
    System.out.println("Barrier2 constructor ends.");
  } // end Barrier2 constructor


  class Worker extends Thread
  {
    int myid;

    Worker(int id)
    { 
      myid = id;
      System.out.println("worker, myid="+myid+" constructed");
    } // end Worker constructor, work is in 'run'

    public void run()
    {
      System.out.println("worker, myid="+myid+" running");
      try // required for barrier.await()
      {
        for(int job=0; job<Njob; job++)
        {
          System.out.println("workerT1, myid="+myid+", job="+job);
	  barrier.await(); // 1a  master may run
          sleep(1);                                // why sleep needed ?
	  barrier.await(); // 1b  master completed
          sleep(1);

          System.out.println("workerT2, myid="+myid+", job="+job);
	  barrier.await(); // 2a  master may run
          sleep(1);
	  barrier.await(); // 2b  master completed
          sleep(1);
	} // end job loop 
	barrier.await(); // 3a  master may run
        sleep(1);
      }
      catch (InterruptedException ex)
      { 
        System.out.println("interrupted exception");
	return; 
      }
      catch (BrokenBarrierException ex)
      { 
        System.out.println("broken barrier exception");
        return; 
      } // end try
    } // end run
  } // end class Worker

  static public void main(String[] args)
  {
    new Barrier2();
    System.out.println("Barrier2 main ending");
  } // end main
} // end class Barrier2

