import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Main
{
	public static void main (String[] args) throws java.lang.Exception
	{
		CountDownLatch latch = new CountDownLatch(3);
		ExecutorService exec = Executors.newCachedThreadPool();

		exec.execute(new WaitingTask(latch));

		exec.execute(new Workers(latch,1));
		exec.execute(new Workers(latch,2));
		exec.execute(new Workers(latch,3));

	}
}

class WaitingTask implements Runnable {
	private CountDownLatch latch;

	public WaitingTask(CountDownLatch latch) {
		this.latch = latch;
	}

	public void run() {
		try {
			System.out.println(this + ": waiting for other tasks to end");
			latch.await();
			System.out.println(this + ": I AM FREE!!!");
		} catch (InterruptedException e) {
			//TODO
		}
	}

	public String toString() {
		return "WaitingTask";
	}
}

class Workers implements Runnable {
	private Random random = new Random();
	private final int id;
	private CountDownLatch latch;

	public Workers(CountDownLatch latch, int id) {
		this.latch = latch;
		this.id = id;
	}

	public void run() {
		try {
			System.out.println(this + ": doing some work");
			TimeUnit.MILLISECONDS.sleep(random.nextInt(2000));

			latch.countDown();
		} catch (InterruptedException e) {
			//TODO
		}
	}

	public String toString() {
		return String.format("Worker %3d", id);
	}
}