import java.util.HashMap; import java.util.HashSet; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Spinneri { // vanligvis en separat monitor // dette objektet skal tr?dene 亚博娱乐官网_亚博pt手机客户端登录e om public String navn; public HashMap materialer = new HashMap<>(); public int antallNoester = 0; public Lock laas = new ReentrantLock(); // én l?s til hele klassen, dvs. at kun én tr?d kan utf?re en oppgave i en kritisk region til enhver tid // conditions som jobber p? den samme l?sen public Condition plassTilMerMohair = laas.newCondition(); public Condition plassTilMerSilke = laas.newCondition(); public Condition nokMaterialer = laas.newCondition(); public boolean ferdig = false; public final int ANTALL_NOESTER; public Spinneri(String navn, HashSet garntyper, int ANTALL_NOESTER) { this.navn = navn; this.ANTALL_NOESTER = ANTALL_NOESTER; for (String type : garntyper) { materialer.put(type, 0); } } public void importerMohair() { laas.lock(); // tr?dene venter her n?r én tr?d har g?tt inn i metoden. Denne tr?den "eier" da l?sen try { // vi importerer 100 gram mohair hver gang og har plass til 1000 while (!ferdig && (materialer.get("Mohair") + 100) > 1000) { try { // hvis en tr?d m? vente her, kommer flere inn og venter her sammen plassTilMerMohair.await(); // N?r en annen metode signaliserer at det n? er plass til mer mohair, vil tr?den som vekkes pr?ve ? ta over l?sen og sjekke betingelsen i while-l?kka p? nytt f?r den evt. g?r videre og utf?rer resten av koden i metoden } catch (InterruptedException e) { System.out.println("Tr?den ble avbrutt"); } } // n?r vi er ute her, vil én tr?d g? videre if (!ferdig) { materialer.put("Mohair", materialer.get("Mohair") + 100); if (materialer.get("Silke") >= 7) { nokMaterialer.signalAll(); // gir beskjed til alle andre tr?der som venter p? nokMaterialer } } } finally { laas.unlock(); // unng?r deadlocks, dvs. at en metode aldri blir l?st opp igjen mens vi har ventende tr?der //Etter at l?sen er ?pnet, vil alle de oppdaterte variablene (tilstanden i programmet) bli synlige for de andre tr?dene } } public void importerSilke() { laas.lock(); // tr?dene venter her n?r én tr?d har g?tt inn i metoden try { // vi importerer 50 gram silke hver gang, og har plass til 750 while (!ferdig && (materialer.get("Silke") + 50) > 750) { try { // hvis en tr?d m? vente her, kommer flere inn og venter her sammen plassTilMerSilke.await(); } catch (InterruptedException e) { System.out.println("Tr?den ble avbrutt"); } } // n?r vi er ute her, vil én tr?d g? videre if (!ferdig) { materialer.put("Silke", materialer.get("Silke") + 50); if (materialer.get("Mohair") >= 18) { nokMaterialer.signalAll(); // gir beskjed til alle andre tr?der som venter p? nokMaterialer // signalAll() ?ker robustheten sammenlignet med signal(), som kun vekker én tr?d } } } finally { laas.unlock(); // unng?r deadlocks } } public void spinnSilkMohair() { laas.lock(); try { // Med en while-l?kke f?r vi at tr?dene venter aktivt p? ? utf?re oppgaven sin while (!ferdig && (materialer.get("Mohair") < 18 || materialer.get("Silke") < 7)) { try { nokMaterialer.await(); // hvis en tr?d m? vente her, slippes l?sen, og flere tr?der kan komme og vente her sammen med den // n?r l?sen slippes kan en annen tr?d bruke den i en annen metode, hvilken tr?d det blir avhenger av tr?dprioritet, "fairness policy" og operativsystemet } catch (InterruptedException e) { System.out.println("Tr?den ble avbrutt"); } } // sjekker om vi ikke er ferdige for ? slippe ? utf?re mer hvis vi er det if (!ferdig) { materialer.put("Mohair", materialer.get("Mohair") - 18); materialer.put("Silke", materialer.get("Silke") - 7); antallNoester++; if (antallNoester >= ANTALL_NOESTER) { ferdig = true; } // vi m? huske ? signalisere dersom vi n? har nok plass til mer materialer if ((materialer.get("Mohair") + 100) <= 1000) { plassTilMerMohair.signalAll(); } if ((materialer.get("Silke") + 50) <= 750) { plassTilMerSilke.signalAll(); } } } finally { laas.unlock(); } } public int antallNoester() { laas.lock(); try { return antallNoester; } finally { laas.unlock(); } } public boolean kjoepGarn() { laas.lock(); try { if (antallNoester >= 8) { // sjekker om vi har nok garn til en Kumulus Bluse, dette tallet kunne vi evt. sendt med som paramter til metoden (det hadde gjort den bedre) antallNoester -= 8; // antall n?ster minker return true; } return false; // husk ? returnere inni try-blokka } finally { laas.unlock(); } } }