import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.*; class FoodTruck { public static final int TOTAL_TACOS = 50; public static final int TOTAL_KUNDER = 25; public static final int MAX_TACOS_ON_COUNTER = 2; public static final int TACO_MAKING_TIME_MS = 1000; private final Lock lc = new ReentrantLock(); Condition ikkeTom = lc.newCondition(); Condition ikkeFull = lc.newCondition(); int taco_on_counter = 0; public void makeTaco() throws InterruptedException { lc.lock(); try { while(taco_on_counter >= FoodTruck.MAX_TACOS_ON_COUNTER) { ikkeFull.await(); } taco_on_counter++; System.out.println("Total tacos on counter: " + taco_on_counter); ikkeTom.signalAll(); } finally { lc.unlock(); } } public void consumeTaco() throws InterruptedException { lc.lock(); try { while(taco_on_counter == 0) { ikkeTom.await(); } taco_on_counter--; System.out.println("Consumed. Tacos on counter: " + taco_on_counter); ikkeFull.signalAll(); } finally { lc.unlock(); } } } class Chef implements Runnable { private final FoodTruck monitor; Chef(FoodTruck monitor) { this.monitor = monitor; } @Override public void run() { try { for(int i = 0; i < FoodTruck.TOTAL_TACOS; i++) { Thread.sleep(FoodTruck.TACO_MAKING_TIME_MS); monitor.makeTaco(); } } catch(InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("Chef interrupted."); } } } class Customer implements Runnable { private FoodTruck monitor; private CountDownLatch cd; Customer(FoodTruck monitor, CountDownLatch cd) { this.monitor = monitor; this.cd = cd; } public void run() { try { Thread.sleep(3000); monitor.consumeTaco(); } catch(InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("Customer interrupted!"); } finally { cd.countDown(); } } } class Main { public static void main(String[] args) { CountDownLatch cd = new CountDownLatch(FoodTruck.TOTAL_KUNDER); FoodTruck monitor = new FoodTruck(); Thread chef1 = new Thread(new Chef(monitor)); Thread chef2 = new Thread(new Chef(monitor)); chef1.start(); chef2.start(); Thread[] customers = new Thread[FoodTruck.TOTAL_KUNDER]; for(int i = 0; i < FoodTruck.TOTAL_KUNDER; i++) { customers[i] = new Thread(new Customer(monitor, cd)); customers[i].start(); } try { cd.await(); chef1.interrupt(); chef2.interrupt(); } catch(InterruptedException e) { System.out.println("Interrupted!"); System.exit(1); } System.out.println("All customers served!"); } }