r2d290 Skrevet 21. februar 2013 Del Skrevet 21. februar 2013 Etter å ha fått til PriorityQueue er jeg nå igang med en ny oppgave. Brukeren skal skrive inn en setning som skal legges inn i en PriorityQueue. Deretter skal 3 tråder konkurere om å hente ut det brukeren hadde skrevet inn. Et krav er at dette blir gjort synkronisert, slik at kun en tråd kan lese fra (og skrive til) ved ethvert tidspunkt. Dette kan gjøres ved at trådene deler et objekt "Guard" som har synkronisert tilgang. Det at oppgaven bruker ordet "kan" betyr at vi kan velge alternative måter å gjøre dette på. Det står i midlertid i klartekst at PriorityQueue skal brukes, så jeg tror ikke det er greit å bruke hverken "PriorityBlockingQueue" eller SynchronizedPriorityQueue. Jeg ser for meg at jeg må gjøre følgende: Lage en synkronisert klasse "Guard" som vidresender PriorityQueue'en som den får fra de tre trådene, til utskriftsklassen Lage et objekt av denne klassen Starte de tre trådene, som sender parameter for PriorityQueue'en til Guard-objektet. Høres det ut som jeg tenker riktig? Nedenfor er koden jeg har til nå, som ikke er synkronisert. import java.util.PriorityQueue; import java.util.Scanner; class OutputVoiceThread implements Runnable { private String name; private PriorityQueue<String> queue; public OutputVoiceThread( String myName, PriorityQueue<String> queue ) { name = myName; this.queue = queue; } public void run() { int count = 0; while(queue.size() != 0) { System.out.println( "Thread : " + name + ", prints : " + queue.poll() ); count++; } System.out.println("Number of printouts from thread " + name + ": " + count); } } public class threadHearUser { static PriorityQueue< String > queue = new PriorityQueue< String >(); static Scanner sc = new Scanner( System.in ); public static void run() { System.out.println( "****The threads want to hear the user****" ); System.out.println("What do you have to say?"); userVoice( sc.nextLine() ); //Gets the input from user System.out.println(); pressAnyKey.pressAnyKey(); } public static void userVoice(String sentence) { queue.clear(); //Clears the queue to remove elements from last run String[] words = sentence.split( "\\s" ); for( String word : words ) { queue.offer(word); //Inserts elements into priority queue } System.out.println( "Words are now added to PriorityQueue. The competition will now start."); pressAnyKey.pressAnyKey(); OutputVoiceThread a = new OutputVoiceThread("A", queue ); Thread threadA = new Thread(a); OutputVoiceThread b = new OutputVoiceThread("B", queue ); Thread threadB = new Thread(b); OutputVoiceThread c = new OutputVoiceThread("C", queue ); Thread threadC = new Thread(c); threadA.start(); threadB.start(); threadC.start(); } } Lenke til kommentar
Mads-b Skrevet 21. februar 2013 Del Skrevet 21. februar 2013 (endret) Du har en alternativ løsning, som er sinnsykt lett, men krever Java 1.6. Collections.synchronizedCollection(din kø her) gjør at Collections rammeverket synkroniserer for deg. Du har da imidlertid kun tilgang til metodene fra Collection klassen, som er litt funksjonsfattig. Måten du tenker på er også helt riktig. Bare husk at selv om du har et "guard"-objekt, som kun leverer ut køen din, betyr ikke dette at priorityqueue på magisk vis nå er synkronisert. Du må "låse" køen til en tråd er ferdig med den. Foreslår følgende: private CountdownLatch lock = new CountdownLatch(0); public Queue<String> getQueue() { lock.await(); lock = new CountdownLatch(1); return queue; } public void unlockQueue() { lock.countDown(); } En countdownLatch gir deg muligheten til å tvinge tråder til å vente til den er 0. På denne måten blokker getQueue() for alle tråder unntatt den som kalte dette først, og først når noen kaller unlockQueue(), kan andre endre. Dette er vel den løsningen jeg har sett som er mest robust og eksplisitt. I motsetning til synkronisering, gjør dette også at man kan gjøre flere ting i seriell på en tråd før andre slipper til. Men det krever litt disiplin med å kalle unlockQueue etter hver gang man er ferdig, i tillegg til at man ikke har noen garanti for at andre tråder kaller unlockQueue og "stjeler" køen som er i bruk. En fiks for dette ville vært å lagre trådnummeret til tråden som låser, og avvise forespørsler fra andre tråder om å låse opp. Endret 21. februar 2013 av Mads-b Lenke til kommentar
r2d290 Skrevet 21. februar 2013 Forfatter Del Skrevet 21. februar 2013 Takk skal du ha! Jeg tror jeg fikk det til på et vis til slutt Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå