Presentasjon lastes. Vennligst vent

Presentasjon lastes. Vennligst vent

Kapittel 23 (Big Java 2.utg) Tråder. Kjøring av tråder Ein tråd er ein del av eit program som blir eksekvert uavhengig av andre deler av programmet Vi.

Liknende presentasjoner


Presentasjon om: "Kapittel 23 (Big Java 2.utg) Tråder. Kjøring av tråder Ein tråd er ein del av eit program som blir eksekvert uavhengig av andre deler av programmet Vi."— Utskrift av presentasjonen:

1 Kapittel 23 (Big Java 2.utg) Tråder

2 Kjøring av tråder Ein tråd er ein del av eit program som blir eksekvert uavhengig av andre deler av programmet Vi kan sjå på ein tråd som ein mini-prosess Deler enkelte ressurser med andre tråder i same prosess Runtime-miljøet JVM (Java Virtual Machine) gir kvar tråd ei viss kjøretid, og kjører trådane etter tur Utanfrå ser det ut som trådane kjører samtidig

3 Kjøring av tråder Kva skal vi med dette? Er det ikkje berre å skrive kode og kjøre ting sekvensielt, altså i rekkefølgje slik at ei og ei oppgåve blir kjørt ferdig? Faktisk ikkje alltid... Weblesar som laster opp fleire bilde “samtidig” Animasjoner med “samtidige” rørsler Og mange andre ting...

4 Kjøring av tråder Java-kode for å kjøre ein tråd: 1. Skriv ein klasse som implementerer interfacet Runnable. Runnable har ein metode: void run() 2. Skriv kode for det du vil ha gjort inne i run() – metoden til klassen din 3. Opprett ein objekt av klassen din 4. Lag eit objekt av klassen Thread med objektet du nettopp laga som argument 5. Kall start() – metoden i Thread -objektet

5 Kjøring av tråder Vi kodar GreetingRunnable-eksemplet Skrive ut tidspunkt og ei helsing, vent eit sekund og gjenta (10 gonger) Klasse som implementerer Runnable, må ha run() – metode main() – metode som lagar to objekt av klassen vi har skrive, og som deretter lagar to Thread -objekt for å kjøre run() – metoden på kvar sitt objekt, tilsynelatande parallelt Vi kjører ved å kalle på start() – metoden i Thread – klassen Ikkje run() – metoden i klassen vi nettopp skreiv, i så fall blir dei to kalla kjørt etter kvarandre static sleep() – metode i Thread for å vente try – catch for å fange opp InterruptedException dersom tråden blir forsøkt stansa medan han “søv” For å stanse eksekveringa av ein tråd kan vi avbryte han (interrupt) Interrupt til ein tråd som er i dvale fører til InterruptedException

6 Kjøring av tråder Ved kjøring av eksemplet ser vi at meldingane frå dei to objekta stort sett kjem annankvar gong Viktig å merke seg at kjøremiljøet ikkje nødvendigvis følgjer ei bestemt rekkefølgje Kvar tråd får kjøre ei viss tid (time slice) Deretter blir neste kjøreklare tråd aktivert Tråder som er i sleep() blir ikkje kjørt

7 Kjøring av tråder Alternativ måte å kjøre tråder Subklasse Thread, og override run() – metoden der Gir same resultat som å implementere Runnable- interfacet Vi bør unngå å subklasse Thread dersom vi treng svært mange tråder, eller dersom programmet vårt kjører på små ressurser I så fall kan vi bruke ein pool av tråder, sjå Advanced Topic 23.1 Vi unngår å opprette og avslutte mange tråder som utfører ei lita oppgåva kvar Gjenbruk av tråder er meir effektivt

8 Terminering av tråder Det normale er at kvar tråd kjører ferdig sin run() – metode Det kan imidlertid hende at vi vil avslutte ein tråd tidlegare Aktuelt når fleire tråder er starta for å finne ei løysing på same problem Ein tråd finn løysinga, dei andre bør avslutte Vi bruker interrupt() – metoden for å gi tråden beskjed om å avslutte Tråden er sjølv ansvarleg for å avslutte på ein kontrollert måte Nødvendig “cleanup”, som til dømes å frigi ressurser

9 Terminering av tråder interrupt() – metoden avslutter ikkje tråden direkte, men set ein boolean variabel i tråden sin datastruktur I run() – metoden kaller vi den statiske metoden interrupted() i Thread for å sjekke om interrupt er sendt I så fall: cleanup og exit Viss tråden er i sleep(), kan han ikkje kjøre kode som sjekkar for interrupt sleep() blir terminert med ein InterruptedException når interrupt blir sendt til ein tråd som “søv” Ein slik Exception blir også kasta om vi prøver å kjøre sleep() i ein tråd som har fått interrupt Difor: Om tråden kaller sleep() i kvar iterasjon, legg koden i ei try – catch blokk som fangar opp InterruptedException Opprydding og avslutning i finally – blokk til slutt Denne blir kjørt enten når try – blokka er ferdig, eller etter ein Exception

10 Race conditions Det kan vere problematisk at tråder deler tilgang til eit felles objekt Bankkonto brukt som eksempel Problem: Vi veit ikkje når kjøretida til kvar enkelt tråd er ute, og neste tråd slepp til Dersom ein tråd ikkje får gjort seg ferdig med ein fullstendig operasjon, kan dette føre til feil Vi får ein situasjon der fleire tråder “konkurrerer” om å fullføre ei oppgåve på felles data på ein slik måte at resultatet er tilfeldig og avhengig av når kjøretida til ein tråd er ute I fagspråket kallar vi dette ein “race condition”

11 Race conditions Ved å skrive om koden, viser forfattaren at vi kan få problemet til å oppstå sjeldnare (nesten aldri) Vi kan framleis få tilstander der ei oppgåve er halvvegs fullført Det er faktisk ekstra ille, for då er det vanskelegare å oppdage Før eller seinare vil feil oppstå ved at høgre side av uttrykket er rekna ut, men ikkje tilordna variabelen på venstre side: balance = balance + amount;

12 Synkronisering For å løyse problem av denne typen kan vi bruke låser. Slike objekt blir brukt til å kontrollere tråder som har tilgang til felles ressurser Interfacet Lock og klasser som implementerer dette ReentrantLock er den mest brukte klassen Eit lås-objekt blir lagt til klasser som har metoder som manipulerer felles data, som f eks ein bankkonto

13 Synkronisering Kode som manipulerer den felles ressursen blir omgitt av kall for å låse og låse opp lås-objektet Når ein tråd kaller lock() – metoden, har tråden kontroll over det låste objektet til den same tråden har kalt unlock() I mellomtida vil eventuelle lock() – kall frå andre tråder føre til at desse må vente I tilfelle ein exception blir kasta må vi sikre at unlock() blir utført Difor: try – blokk med kode, deretter unlock() i finally – blokk

14 Synkronisering Enkelt kodeeksempel: public class BankAccount{ private Lock balanceChangeLock; public BankAccount { balanceChangeLock = new ReeantrantLock(); } public void deposit() { balanceChangeLock.lock(); try { // Kode for å sette inn på kontoen } finally { balanceChangeLock.unlock(); }

15 Synkronisering Analogi til ein gammaldags telefonkiosk Trådane er personar som ventar på å bruke telefonkiosken Det er plass til berre ein person samtidig Om kiosken er ledig, går den første inn og “låser” døra Andre som kjem til ser at det er opptatt, og må vente Når førstemann er ferdig og går ut, er det meir eller mindre tilfeldig kven som får tilgang

16 Deadlocks Bruk av låser kan føre til uønska situasjoner Fleire tråder, alle er blokkert på grunn av at andre må utføre noko først Ressurser blir låst utan at arbeid blir gjort ferdig Deadlock!

17 Deadlocks For å unngå deadlocks kan vi bruke condition -objekt, som blir oppretta på låsen Gir tråden lov til midlertidig å gi slipp på låsen for å la andre arbeide, og deretter få igjen låsen Test for å sjekke om arbeid kan utførast blir gjort etter at objektet er låst Om tråden må vente, kall await() Kode som kan føre til at arbeidet kan utførast må kalle signalAll()

18 Deadlocks I bankkonto-eksemplet: Uttak kan ikkje føre til negativ saldo, vi vil i så fall vente på innskudd på kontoen Metoden for uttak sjekkar saldo, om det er for lite på konto kallar vi await() Tråden slepper låsen og blir blokkert. Denne tråden blir ikkje kjørt når det blir “hans tur” Metoden som set inn pengar må kalle signalAll() på det same condition-objektet for å avblokkere tråder som ventar på auka saldo på denne kontoen Etter signalAll() vil tråder som var blokkert igjen bli kjørt på lik linje med andre aktive tråder

19 Deadlocks Merk: Nøyaktig eitt lås-objekt og eitt condition-objekt pr bankkonto, alle tråder opererer på same lock og condition Pass på at alle await() vil bli terminert med signalAll() signalAll() kan berre kallast av ein tråd som har ein lås på vedkommande objekt À propos: Deadlocks er også aktuelt i operativsystem- samanheng Tradisjonelt har problemet blitt ignorert, sjølv om teknikkar har vore kjent Deadlock-handtering er ressurskrevjande Så lenge problemet ikkje har vore påtrengande, har det blitt oversett


Laste ned ppt "Kapittel 23 (Big Java 2.utg) Tråder. Kjøring av tråder Ein tråd er ein del av eit program som blir eksekvert uavhengig av andre deler av programmet Vi."

Liknende presentasjoner


Annonser fra Google