code: import java.util.Random;
  import java.util.concurrent.CountDownLatch;
  
  public class Sync {
  	static class Worker implements Runnable {
  		private final CountDownLatch doneSignal;
  		private int threadID;
  
  		public Worker(int id, CountDownLatch doneSignal) {
  			this.doneSignal = doneSignal;
  			threadID = id;
  		}
  
  		public void run() {
  			doWork();
  			doneSignal.countDown();
  		}
  
  		void doWork() {
  			try {
  				int workTime = new Random().nextInt(900) + 100;
  				System.out.println("Worker " + threadID + " will work for " + workTime + " msec.");
  				Thread.sleep(workTime); //work for 'workTime'
  				System.out.println("Worker " + threadID + " is ready");
  			} catch (InterruptedException e) {
  				System.err.println("Error: thread execution interrupted");
  				e.printStackTrace();
  			}
  		}
  	}
  
  	public static void main(String[] args) {
  		int n = 3;//6 workers and 3 tasks
  		for(int task = 1; task <= n; task++) {
  			CountDownLatch latch = new CountDownLatch(n * 2);
  			System.out.println("Starting task " + task);
  			for(int worker = 0; worker < n * 2; worker++) {
  				new Thread(new Worker(worker, latch)).start();
  			}
  			try {
  				latch.await();//wait for n*2 threads to signal the latch
  			} catch (InterruptedException e) {
  				e.printStackTrace();
  			}
  			System.out.println("Task " + task + " complete");
  		}
  	}
  }
  