import java.util.ArrayList; import java.util.Random; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /* Lag klassen Barista, som er en tråd. Alle har et array med ulike kaffedrikker private final String[] drikker = {"Americano", "Café au lait", "Caffè latte", "Caffè mocca", "Espresso", "Cortado"}; I tillegg tar Baristaen inn et bord (som du skal lage i oppgave E) vedkommende kan servere kaffen på, og en id. */ class Barista implements Runnable{ private Bord bord; private int id; private final String[] drikker = {"Americano", "Café au lait", "Caffè latte", "Caffè mocca", "Espresso", "Cortado"}; public Barista(Bord b, int id){ bord = b; this.id = id; } @Override public void run(){ /* Implementér metoden run i Barista. Hver barista lager ti kaffe, og disse drikkene skal velges tilfeldig fra en liste med drikker (Tips: bruk java.util.Random for å få et tall mellom 0 og lengden til drikker). Baristaen skal skrive ut sin id og hvilken drikke som blir laget før vedkommende serverer kaffen på bordet. Når ti kaffe er servert, skal baristaen melde i fra at vedkommende er ferdig (inkludert id-en til baristaen). */ Random random = new Random(); for (int i = 0; i < 10; i++){ int indeks = random.nextInt(drikker.length); String drikke = drikker[indeks]; bord.serverKaffe(drikke); System.out.println("Barista "+ id + " sererverer en " + drikke); } System.out.println("Barista " +id + " er ferdig. "); } } /* Lag klassen Kaffedrikker, som er en tråd. Kaffedrikker tar inn et bord vedkommende kan hente kaffe fra, og en id. Implementer metode run i Kaffedrikker. Denne skal ha en teller som teller antall kaffer som kaffedrikkeren får drukket. Så lenge kaffedrikeren får beskjed om at det ikke er tomt skal vedkommende printe sin id og hvilken kaffe som ble drukket. Når det ikke er flere kaffer for kaffedrikkeren å drikke skal vedkommende printe sin id og hvor mange kaffekopper som ble drukket. */ class Kaffedrikker implements Runnable{ private Bord bord; private int id; public Kaffedrikker(Bord b, int i){ bord = b; id = i; } @Override public void run(){ // Når vi har implementert Bord og bruker await() ser vi at vi trenger en try catch, fordi await() kaster en InterupptedException som vi må håndtere her. int antKaffe = 0; try{ String kaffe; while ((kaffe = bord.hentKaffe()) != null){ System.out.println("Kaffedrikker " + id + " drikker en " + kaffe); antKaffe++; } } catch(InterruptedException e){ Thread.currentThread().interrupt(); System.out.println("Kaffedrikker " + id + "ble avbrutt."); } finally{ System.out.println("Kaffedrikker " + id + " har drukket "+ antKaffe + " kopper kaffe."); } } } /* Lag klassen Bord. Lag en metode som serverer kaffe (legger de til i bordet). Husk at det kan være uendelig mange kaffer på bordet om gangen. Lag også en metode hentKaffe som henter en kaffe fra bordet så lenge det er en kaffe der, og signaliserer til Kaffedrikker når det er tomt. Lag klassen Hovedprogram som lager et bord, to baristaer og ti kaffedrikkere. Test gjerne med ulike verdier for å se hvordan programmet oppfører seg. */ class Bord{ private ArrayList kopper = new ArrayList<>(); // fordi vi ikke vet hvor mange kopper som skal være på bordet, og bordet blir aldri fullt. private Lock lås = new ReentrantLock(); private Condition ikkeTomt = lås.newCondition(); private int totaltAntallKopper; // antall kopper vi totalt kommer til å få public Bord(int ant){ totaltAntallKopper = ant; } public void serverKaffe(String kopp){ lås.lock(); try{ kopper.add(kopp); totaltAntallKopper--; ikkeTomt.signalAll(); }finally{ lås.unlock(); } } public String hentKaffe() throws InterruptedException{ // .await() kaster interrupptedException og vi må håndtere det. lås.lock(); try{ while(kopper.isEmpty() && totaltAntallKopper > 0){ // Fordi vi ikke vil at kaffedrikker-trådene avslutter mens det fortsatt er baristaer som kommer til å servere kaffe. ikkeTomt.await(); } if (!kopper.isEmpty()){ return kopper.remove(0); } return null; } finally{ lås.unlock(); } } }