Jonny Karlsson PROCESSPROGRAMMERING Föreläsning 8 ( ) Innehåll: Trådprogrammering i Java - Avbrott (”interrupts”) - Metoden join() - Synkronisering
Jonny Karlsson Avbrott Ett avbrott är en signal till en tråd om att den borde avsluta det den gör just nu. Vanligast är att ett avbrott avslutar en tråd, men det är upp till programmeraren själv vad som skall ske när ett avbrott uppstår. En tråd kan skicka ett avbrott till en annan tråd genom att anropa metoden interrupt() som är definierad i klassen Thread (Se API specificationen).. //skapar och startar en tråd Thread th = new Thread(this); th.start();.. //gör någonting.. //Skickar ett avbrott till tråden th.interrupt();
Jonny Karlsson Avbrott Hur en tråd reagerar på ett avbrott beror på vad tråden gör just vid den tidpunkt ett avbrott uppstår. Om en tråd vid jämna mellanrum anropar metoder som kastar InterruptedException kan trådens run-metod programmeras att returnera genast efter att den fångat upp undantaget:while(true){ //gör något..try{Thread.sleep(1000);} catch(InterruptedException e) { //Denna tråd blev avbruten return 0; }}
Jonny Karlsson Avbrott Många metoder som kastar InterruptedException (t.ex. sleep()) är designade på ett sådant sätt att de avbryter sin nuvarande funktion och returnerar genast när ett avbrott tagits emot. Om en tråd utför någonting för en lång tid utan att anropa en metod som kastar InterruptedException måste den periodvis kolla om den blivit avbruten för att kunna stöda avbrott. Metoden interrupted() i klassen Thread returnerar true om innevarande tråd har tagit emot ett avbrott.
Jonny Karlsson Avbrott Exempel:while(true){System.out.println(”HelloWorld!!!!!”);if(Thread.interrupted()){ System.out.println(”Denna tråd tog emot ett avbrott!!”); return;}} Koden ovan helt enkelt returnerar och avslutar tråden om den tar emot ett avbrott.
Jonny Karlsson Avbrott Avbrottsmekanismen är implementerad genom att använda en flagga: interrupt status. När man anropar metoden interrupt() aktiveras flaggan interrupted status för den tråd man utförde interrupt() på. När en tråd kollar om den blivit avbruten med Thread.interrupted() kontrolleras det om flaggan är aktiverad eller ej och om den är aktiverad så kommer flaggan igen att bli inaktiv.
Jonny Karlsson Avbrott En tråd kan kontrollera om en annan tråd har tagit emot ett avbrott eller ej med metoden isInterrupted(): if(trad.isInterrupted()) //tråden trad har tagit emot ett avbrott else//tråden trad är fortfarande aktiv OBS! isInterrupted() ändrar inte statuset på flaggan interrupted status.
Jonny Karlsson Metoden join() Metoden join (definierad i klassen thread) tillåter en tråd att vänta på att en annan tråd skall avsluta sin exekvering. Exempel:... //trad är en tråd som för tillfället exekverar trad.join()... I koden ovan ställs innevarande tråd in att vänta på att tråden trad skall avslutas innan den fortsätter sin egen exekvering.
Jonny Karlsson Synkronisering Trådar kommunicerar sinsemellan främst via gemensamma globala variabler. Denna typ av kommunikation är effektiv eftersom inget data behöver fysiskt skickas mellan två eller flera trådar. Kommunikation mellan trådar via gemensamma variabler kan dock ge upphov till två olika typer av problem/fel: Trådkollision (”thread interference”) Minneskonsekvensfel (”memory consistency error”);
Jonny Karlsson Trådkollision Innebär att två eller flera trådar uppdaterar en gemensam variabel samtidigt. Antag att två trådar inkrementerar en gemensam global variabel med 1. Om två trådar inkerementerar borde värdet i den globala variabeln ha ökat med 2. Men om de båda trådarna råkade inkrementera exakt samtidigt blir slutresultatet att den globala variabeln endast ökat med 1.
Jonny Karlsson Synkroniserade metoder Ett sätt i Java att synkronisera trådar som använder en gemensam global variabel är att använda s.k. synkroniserade metoder (”synchronized methods”) För att göra en metod synkroniserad användar man sej av nyckelordet synchronized vid metoddefinitionen: synchronized void minSynkroniseradeMetod() {}
Jonny Karlsson Synkroniserade metoder Exempel: int raknare = 0; synchronized void inkrementera() {raknare++;} Om flera trådar samtidigt anropar den synkroniserade metoden inkrementera() ovan kommer endast en åt gången in i metoden, övriga pausar sina exekveringar och väntar på att föregående tråd skall bli klar.