import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.System.out;
public class SantaClaus {
private volatile boolean kidsStillBelieveInSanta = true;
private final Semaphore disbelief = new Semaphore(0);
private final static int END_OF_FAITH = 2012;
private AtomicInteger year = new AtomicInteger(2006);
private static Random generator = new Random();
private final static int NUMBER_OF_REINDEER = 9;
private final static int NUMBER_OF_ELVES = 10;
private final static int ELVES_NEEDED_TO_WAKE_SANTA = 3;
private final Semaphore queueElves;
private final CyclicBarrier threeElves;
private final CyclicBarrier elvesAreInspired;
private final CyclicBarrier allReindeers;
private final CyclicBarrier sleigh;
private final Semaphore santasAttention;
private final static int LAST_REINDEER = 0; private final static int THIRD_ELF = 0;
class Reindeer implements Runnable {
int id;
Reindeer(int id) { this.id = id; }
public void run() {
while (kidsStillBelieveInSanta) {
try {
Thread.sleep(900 + generator.nextInt(200));
int reindeer = allReindeers.await();
if (reindeer == LAST_REINDEER) {
santasAttention.acquire();
out.println("=== Delivery for Christmas " + year + " ===");
if (year.incrementAndGet() == END_OF_FAITH)
{
kidsStillBelieveInSanta = false;
disbelief.release();
}
}
sleigh.await();
Thread.sleep(generator.nextInt(20));
reindeer = sleigh.await();
if (reindeer == LAST_REINDEER) {
santasAttention.release();
out.println("=== Toys are delivered ===");
}
} catch (InterruptedException e) {
} catch (BrokenBarrierException e) {
}
}
out.println("Reindeer " + id + " retires");
}
}
class Elf implements Runnable {
int id;
Elf(int id) { this.id = id; }
public void run() {
try {
Thread.sleep(generator.nextInt(2000));
while (kidsStillBelieveInSanta) {
queueElves.acquire();
out.println("Elf " + id + " ran out of ideas");
int elf = threeElves.await();
if (elf == THIRD_ELF)
santasAttention.acquire();
Thread.sleep(generator.nextInt(500));
out.println("Elf " + id + " got inspiration");
elvesAreInspired.await();
if (elf == THIRD_ELF)
santasAttention.release();
queueElves.release();
Thread.sleep(generator.nextInt(2000));
}
} catch (InterruptedException e) {
} catch (BrokenBarrierException e) {
}
out.println("Elf " + id + " retires");
}
}
class BarrierMessage implements Runnable {
String msg;
BarrierMessage(String msg) { this.msg = msg; }
public void run() {
out.println(msg);
}
}
class Harnessing implements Runnable {
boolean isSleighAttached;
Harnessing() { isSleighAttached = false; }
public void run() {
isSleighAttached = !isSleighAttached;
if (isSleighAttached)
out.println("=== All reindeer harnessed ===");
else
out.println("=== All reindeer are back in the stable ===");
}
}
public SantaClaus() {
santasAttention = new Semaphore(1, true);
queueElves = new Semaphore(ELVES_NEEDED_TO_WAKE_SANTA, true); threeElves = new CyclicBarrier(ELVES_NEEDED_TO_WAKE_SANTA,
new BarrierMessage("--- " + ELVES_NEEDED_TO_WAKE_SANTA + " elves are knocking ---"));
elvesAreInspired = new CyclicBarrier(ELVES_NEEDED_TO_WAKE_SANTA,
new BarrierMessage("--- Elves return to work ---"));
allReindeers = new CyclicBarrier(NUMBER_OF_REINDEER, new Runnable() {
public void run() {
out.println("=== Reindeer reunion for Christmas " + year +" ===");
}});
sleigh = new CyclicBarrier(NUMBER_OF_REINDEER, new Harnessing());
ArrayList<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < NUMBER_OF_ELVES; ++i)
threads.add(new Thread(new Elf(i)));
for (int i = 0; i < NUMBER_OF_REINDEER; ++i)
threads.add(new Thread(new Reindeer(i)));
out.println("Once upon in the year " + year + " :");
for (Thread t : threads)
t.start();
try {
disbelief.acquire();
out.println("Faith has vanished from the world");
for (Thread t : threads)
t.interrupt();
for (Thread t : threads)
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
out.println("The End of Santa Claus");
}
public static void main(String[] args) {
new SantaClaus();
}
}