Livssyklus for en tråd i Java
1. Introduksjon
I denne artikkelen vil vi diskutere i detalj et kjernekonsept i Java - livssyklusen til en tråd.
Vi bruker et raskt illustrert diagram og, selvfølgelig, praktiske kodebiter for å bedre forstå disse tilstandene under utførelsen av tråden.
For å komme i gang med å forstå tråder i Java, er denne artikkelen om å lage en tråd et godt sted å starte.
2. Multitrading i Java
På Java-språket drives multitrading av kjernekonseptet med en tråd. I løpet av livssyklusen går tråder gjennom forskjellige tilstander:
3. Livssyklus for en tråd i Java
De java.lang.Tråd klasse inneholder en statisk stat enum - som definerer dets potensielle tilstander. I løpet av et gitt tidspunkt kan tråden bare være i en av disse tilstandene:
- NYHET - en nyopprettet tråd som ennå ikke har startet utførelsen
- RUNNABLE - enten kjører eller klar for kjøring, men det venter på ressurstildeling
- BLOKERT - venter på å anskaffe en skjermlås for å gå inn eller angi en synkronisert blokk / metode på nytt
- VENTER - venter på at en annen tråd skal utføre en bestemt handling uten tidsbegrensning
- TIMED_WAITING - venter på at en annen tråd skal utføre en bestemt handling i en spesifisert periode
- AVSLUTTET - har fullført henrettelsen
Alle disse tilstandene er dekket i diagrammet ovenfor; la oss nå diskutere hver av disse i detalj.
3.1. Ny
EN NYTråd (eller en født Tråd) er en tråd som er opprettet, men som ennå ikke er startet. Det forblir i denne tilstanden til vi begynner å bruke start() metode.
Følgende kodebit viser en nylig opprettet tråd som er i NY stat:
Runnable runnable = new NewState (); Tråd t = ny tråd (kan kjøres); Log.info (t.getState ());
Siden vi ikke har startet den nevnte tråden, er metoden t.getState () utskrifter:
NY
3.2. Kjørbar
Når vi har opprettet en ny tråd og kalt start() metode på det, er det flyttet fra NY til RUNNABLE stat. Tråder i denne tilstanden kjøres enten eller er klare til å kjøres, men de venter på ressurstildeling fra systemet.
I et miljø med flere tråder tildeler trådtidsplanleggeren (som er en del av JVM) en fast tid til hver tråd. Så det går i en bestemt periode, og deretter avgir kontrollen til andre RUNNABLE tråder.
La oss for eksempel legge til t.start () metode til vår forrige kode og prøv å få tilgang til den nåværende tilstanden:
Runnable runnable = new NewState (); Tråd t = ny tråd (kan kjøres); t.start (); Log.info (t.getState ());
Denne koden er mest sannsynlig for å returnere utdata som:
RUNNABLE
Merk at i dette eksemplet er det ikke alltid garantert at når kontrollen når t.getState (), vil det være fremdeles i RUNNABLE stat.
Det kan hende at den ble umiddelbart planlagt av Trådplanlegger og kan fullføre utførelsen. I slike tilfeller kan vi få en annen produksjon.
3.3. Blokkert
En tråd er i BLOKERT oppgi når den for øyeblikket ikke er kvalifisert for å kjøre. Den går inn i denne tilstanden når den venter på en skjermlås og prøver å få tilgang til en kodeseksjon som er låst av en annen tråd.
La oss prøve å gjengi denne tilstanden:
offentlig klasse BlockedState {offentlig statisk tomrom hoved (String [] args) kaster InterruptedException {Thread t1 = new Thread (new DemoThreadB ()); Tråd t2 = ny tråd (ny DemoThreadB ()); t1.start (); t2.start (); Tråd. Søvn (1000); Log.info (t2.getState ()); System.exit (0); }} klasse DemoThreadB implementerer Runnable {@Override public void run () {commonResource (); } offentlig statisk synkronisert tomrom commonResource () {while (true) {// Infinite loop for å etterligne tung prosessering // 't1' vil ikke forlate denne metoden // når 't2' prøver å legge inn denne}}}
I denne koden:
- Vi har laget to forskjellige tråder - t1 og t2
- t1 starter og går inn i det synkroniserte commonResource () metode; dette betyr at bare en tråd kan få tilgang til den; alle andre påfølgende tråder som prøver å få tilgang til denne metoden vil bli blokkert fra videre kjøring til den nåværende vil fullføre behandlingen
- Når t1 går inn i denne metoden, holdes den i en uendelig mens løkke; dette er bare for å etterligne tung prosessering slik at alle andre tråder ikke kan gå inn i denne metoden
- Nå når vi begynner t2, prøver den å gå inn i commonResource () metoden, som allerede nås av t1, og dermed, t2 vil bli holdt i BLOKERT stat
Å være i denne tilstanden, kaller vi t2.getState () og få utdataene som:
BLOKERT
3.4. Venter
En tråd er inne VENTER angi når den venter på at en annen tråd skal utføre en bestemt handling. I følge JavaDocs kan hvilken som helst tråd komme inn i denne tilstanden ved å ringe en av følgende tre metoder:
- object.wait ()
- thread.join () eller
- LockSupport.park ()
Legg merke til at i vente() og bli med() - vi definerer ikke noen tidsavbruddsperiode, da dette scenariet blir dekket i neste avsnitt.
Vi har en egen veiledning som i detalj diskuterer bruken av vente(), gi beskjed() og notifyAll ().
For nå, la oss prøve å gjengi denne tilstanden:
offentlig klasse WaitingState implementerer Runnable {public static Thread t1; public static void main (String [] args) {t1 = new Thread (new WaitingState ()); t1.start (); } public void run () {Thread t2 = new Thread (new DemoThreadWS ()); t2.start (); prøv {t2.join (); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); Log.error ("Tråden avbrutt", e); }}} klasse DemoThreadWS implementerer Runnable {public void run () {try {Thread.sleep (1000); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); Log.error ("Tråden avbrutt", e); } Log.info (WaitingState.t1.getState ()); }}
La oss diskutere hva vi gjør her:
- Vi har opprettet og startet t1
- t1 skaper en t2 og starter den
- Mens behandlingen av t2 fortsetter, ringer vi t2. bli med (), dette setter t1 i VENTER tilstand til t2 er ferdig utført
- Siden t1 venter på t2 for å fullføre, ringer vi t1.getState () fra t2
Resultatet her er, som du forventer:
VENTER
3.5. Tidsbestemt venting
En tråd er inne TIMED_WAITING angi når den venter på at en annen tråd skal utføre en bestemt handling innen en bestemt tid.
I følge JavaDocs er det fem måter å sette en tråd på TIMED_WAITING stat:
- thread.sleep (long millis)
- vent (int timeout) eller vent (int timeout, int nanos)
- thread.join (lang millis)
- LockSupport.parkNanos
- LockSupport.parkUntil
For å lese mer om forskjellene mellom vente() og søvn() i Java, ta en titt på denne dedikerte artikkelen her.
For nå, la oss prøve å reprodusere raskt denne tilstanden:
offentlig klasse TimedWaitingState {public static void main (String [] args) kaster InterruptedException {DemoThread obj1 = new DemoThread (); Tråd t1 = ny tråd (obj1); t1.start (); // Følgende søvn vil gi nok tid til ThreadScheduler // til å starte behandlingen av tråden t1 Thread.sleep (1000); Log.info (t1.getState ()); }} klasse DemoThread implementerer Runnable {@Override public void run () {try {Thread.sleep (5000); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); Log.error ("Tråden avbrutt", e); }}}
Her har vi opprettet og startet en tråd t1 som settes i hviletilstand med en tidsavbruddsperiode på 5 sekunder; utgangen vil være:
TIMED_WAITING
3.6. Avsluttet
Dette er tilstanden til en død tråd. Det er i AVSLUTTET angi når den enten er ferdig utført eller ble avsluttet unormalt.
Vi har en dedikert artikkel som diskuterer forskjellige måter å stoppe tråden på.
La oss prøve å oppnå denne tilstanden i følgende eksempel:
offentlig klasse TerminatedState implementerer Runnable {public static void main (String [] args) throw InterruptedException {Thread t1 = new Thread (new TerminatedState ()); t1.start (); // Følgende hvilemetode vil gi nok tid til // tråd t1 til å fullføre Thread.sleep (1000); Log.info (t1.getState ()); } @ Override public void run () {// Ingen behandling i denne blokken}}
Her, mens vi har startet tråden t1, den neste uttalelsen Thread.sleep (1000) gir nok tid til t1 å fullføre, og dette programmet gir oss resultatet som:
AVSLUTTET
I tillegg til trådtilstanden, kan vi sjekke er i live() metode for å avgjøre om tråden er i live eller ikke. For eksempel hvis vi kaller er i live() metode på denne tråden:
Assert.assertFalse (t1.isAlive ());
Det kommer tilbake falsk. Enkelt sagt, en tråd er i live hvis og bare hvis den har blitt startet og har ennå ikke død.
4. Konklusjon
I denne opplæringen lærte vi om livssyklusen til en tråd i Java. Vi så på alle seks stater definert av Tråd. Stat enum og gjengitt dem med raske eksempler.
Selv om kodebitene vil gi samme utgang i nesten alle maskiner, kan vi i noen unntakstilfeller få noen forskjellige utganger, ettersom den eksakte oppførselen til trådplanleggeren ikke kan bestemmes.
Og som alltid er kodebitene som brukes her, tilgjengelige på GitHub.