import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; public class Monitor { public static enum Veicolo { AUTO_PUBBLICA, AUTO_PRIVATA, BARCA; } private final Lock lock = new ReentrantLock(); private final CountingCondition attesaAutoPrivate = new CountingCondition(lock, "auto pri"); private final CountingCondition attesaAutoPubbliche = new CountingCondition(lock, "auto pub"); private final CountingCondition attesaBarche = new CountingCondition(lock, "barche"); // Variabili di stato private boolean ponteAperto = false; private int autoInTransito = 0; private int barcheInTransito = 0; // Variabili passate dal costruttore private final int maxMacchineInTransito; public Monitor(final int maxMacchine) { this.maxMacchineInTransito = maxMacchine; } public void entraPonte(Veicolo veicolo) throws InterruptedException { try { lock.lock(); System.out.println("Sta entrando un " + veicolo); if (veicolo == Veicolo.BARCA) { final Supplier<Boolean> condition = () -> { return ponteAperto || autoInTransito == 0; }; attesaBarche.waitUntil(condition); // Apri ponte se era chiuso if (!ponteAperto) { ponteAperto = true; } barcheInTransito++; } else if (veicolo == Veicolo.AUTO_PUBBLICA) { final Supplier<Boolean> condition = () -> { return (!ponteAperto || barcheInTransito == 0) && autoInTransito < maxMacchineInTransito && attesaBarche.nobodyWaiting(); }; attesaAutoPubbliche.waitUntil(condition); // Se aperto chiudi il ponte if (ponteAperto) { ponteAperto = false; } autoInTransito++; } else if (veicolo == Veicolo.AUTO_PRIVATA) { final Supplier<Boolean> condition = () -> { return (!ponteAperto || barcheInTransito == 0) && autoInTransito < maxMacchineInTransito && attesaBarche.nobodyWaiting() && attesaAutoPubbliche.nobodyWaiting(); }; attesaAutoPrivate.waitUntil(condition); // Se aperto chiudi il ponte if (ponteAperto) { ponteAperto = false; } autoInTransito++; printInfo(); } else throw new IllegalArgumentException(); } finally { lock.unlock(); } } private void printInfo() { System.out.println("ponteAperto = " + ponteAperto + "\nautoInTransito = " + autoInTransito + "\nbarcheIntransito = " + barcheInTransito); } public void esciPonte(Veicolo veicolo) { try { lock.lock(); System.out.println("Esce un " + veicolo); printInfo(); if (veicolo == Veicolo.BARCA) { barcheInTransito--; attesaBarche.signalAll(); attesaAutoPubbliche.signalAll(); attesaAutoPrivate.signalAll(); } else if (veicolo == Veicolo.AUTO_PRIVATA || veicolo == Veicolo.AUTO_PUBBLICA) { autoInTransito--; attesaBarche.signalAll(); attesaAutoPubbliche.signalAll(); attesaAutoPrivate.signalAll(); } else throw new IllegalArgumentException(); } finally { lock.unlock(); } } }