Trådens livscyklus i Java

1. Introduktion

I denne artikel diskuterer vi detaljeret et kernekoncept i Java - livets cyklus for en tråd.

Vi bruger et hurtigt illustreret diagram og selvfølgelig praktiske kodestykker til bedre at forstå disse tilstande under udførelsen af ​​tråden.

For at komme i gang med at forstå tråde i Java er denne artikel om oprettelse af en tråd et godt sted at starte.

2. Multithreading i Java

På Java-sproget drives multithreading af kernekonceptet med en tråd. I løbet af deres livscyklus går tråde gennem forskellige tilstande:

3. En tråds livscyklus i Java

Det java.lang.Tråd klasse indeholder en statisk stat enum - som definerer dens potentielle tilstande. I løbet af et givet tidspunkt kan tråden kun være i en af ​​disse tilstande:

  1. NYHED - en nyoprettet tråd, der endnu ikke har startet udførelsen
  2. KØRSEL - enten kørende eller klar til udførelse, men det venter på ressourcetildeling
  3. BLOKERET - venter på at erhverve en monitorlås for at gå ind eller genindtaste en synkroniseret blok / metode
  4. VENTER - venter på, at en anden tråd udfører en bestemt handling uden nogen tidsbegrænsning
  5. TIMED_WAITING - venter på, at en anden tråd udfører en bestemt handling i en bestemt periode
  6. AFSLUTTET - har afsluttet sin udførelse

Alle disse tilstande er dækket i diagrammet ovenfor; lad os nu diskutere hver af disse detaljeret.

3.1. Ny

EN NYTråd (eller en født Tråd) er en tråd, der er oprettet, men endnu ikke startet. Det forbliver i denne tilstand, indtil vi begynder at bruge det Start() metode.

Følgende kodestykke viser en nyoprettet tråd, der er i NY stat:

Kørbar kørbar = ny NewState (); Tråd t = ny tråd (kan køres); Log.info (t.getState ());

Da vi ikke har startet den nævnte tråd, er metoden t.getState () udskrifter:

NY

3.2. Kan køres

Når vi har oprettet en ny tråd og kaldt Start() metode på det, er det flyttet fra NY til KØRSEL stat. Tråde i denne tilstand kører enten eller er klar til at køre, men de venter på ressourcetildeling fra systemet.

I et miljø med flere tråde tildeler tråd-planlæggeren (som er en del af JVM) en fast tid til hver tråd. Så det kører i en bestemt periode og derefter afstår kontrollen til andre KØRSEL tråde.

Lad os f.eks. Tilføje t.start () metode til vores tidligere kode, og prøv at få adgang til dens aktuelle tilstand:

Kørbar kørbar = ny NewState (); Tråd t = ny tråd (kan køres); t.start (); Log.info (t.getState ());

Denne kode er højst sandsynlig for at returnere output som:

KØRSEL

Bemærk, at i dette eksempel er det ikke altid garanteret, at når vores kontrol når t.getState (), det vil stadig være i KØRSEL stat.

Det kan ske, at det straks blev planlagt af Trådplanlægning og kan afslutte udførelsen. I sådanne tilfælde kan vi få en anden output.

3.3. Blokeret

En tråd er i BLOKERET angive, hvornår det i øjeblikket ikke er kvalificeret til at køre. Det går ind i denne tilstand, når det venter på en monitorlås og forsøger at få adgang til et afsnit af kode, der er låst af en anden tråd.

Lad os prøve at gengive denne tilstand:

offentlig klasse BlockedState {offentlig statisk ugyldig 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 synkroniseret tomrum commonResource () {while (true) {// Infinite loop for at efterligne tung behandling // 't1' forlader ikke denne metode // når 't2' prøver at indtaste denne}}}

I denne kode:

  1. Vi har oprettet to forskellige tråde - t1 og t2
  2. t1 starter og går ind i det synkroniserede commonResource () metode; dette betyder, at kun en tråd kan få adgang til den; alle andre efterfølgende tråde, der forsøger at få adgang til denne metode, blokeres fra den yderligere udførelse, indtil den nuværende vil afslutte behandlingen
  3. Hvornår t1 går ind i denne metode, holdes den i en uendelig mens løkke; dette er bare for at efterligne tung behandling, så alle andre tråde ikke kan komme ind i denne metode
  4. Nu når vi starter t2, det forsøger at komme ind i commonResource () metode, som allerede er åbnet af t1, dermed, t2 opbevares i BLOKERET stat

At være i denne tilstand, kalder vi t2.getState () og få output som:

BLOKERET

3.4. Venter

En tråd er inde VENTER angive, når det venter på en anden tråd til at udføre en bestemt handling. Ifølge JavaDocs kan enhver tråd komme ind i denne tilstand ved at ringe til en af ​​følgende tre metoder:

  1. object.wait ()
  2. thread.join () eller
  3. LockSupport.park ()

Bemærk, at i vente() og tilslutte() - vi definerer ikke nogen timeoutperiode, da dette scenarie er dækket i det næste afsnit.

Vi har en separat vejledning, der detaljeret diskuterer brugen af vente(), underrette() og notifyAll ().

Lad os nu prøve at gengive denne tilstand:

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 afbrudt", e); }}} klasse DemoThreadWS implementerer Runnable {public void run () {try {Thread.sleep (1000); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); Log.error ("Tråden afbrudt", e); } Log.info (WaitingState.t1.getState ()); }}

Lad os diskutere, hvad vi laver her:

  1. Vi har oprettet og startet t1
  2. t1 skaber en t2 og starter det
  3. Mens behandlingen af t2 fortsætter, kalder vi t2.tilslut (), dette sætter t1 i VENTER tilstand indtil t2 er færdig med henrettelsen
  4. Siden t1 venter på t2 for at gennemføre, ringer vi t1.getState () fra t2

Outputtet her er, som man kunne forvente:

VENTER

3.5. Tidsbestemt ventetid

En tråd er inde TIMED_WAITING angive, når det venter på en anden tråd til at udføre en bestemt handling inden for en bestemt tid.

Ifølge JavaDocs er der fem måder at sætte en tråd på TIMED_WAITING stat:

  1. thread.sleep (lange millis)
  2. vent (int timeout) eller Vent (int timeout, int nanos)
  3. thread.join (lang millis)
  4. LockSupport.parkNanos
  5. LockSupport.parkUntil

For at læse mere om forskellene mellem vente() og søvn() i Java, se på denne dedikerede artikel her.

Lad os nu prøve at reproducere denne tilstand hurtigt:

offentlig klasse TimedWaitingState {public static void main (String [] args) throw InterruptedException {DemoThread obj1 = new DemoThread (); Tråd t1 = ny tråd (obj1); t1.start (); // Den følgende dvaletilstand giver ThreadScheduler // nok tid til at starte behandlingen af ​​tråden t1 Thread.sleep (1000); Log.info (t1.getState ()); }} klasse DemoThread implementerer Runnable {@Override public void run () {prøv {Thread.sleep (5000); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); Log.error ("Tråden afbrudt", e); }}}

Her har vi oprettet og startet en tråd t1 som er gået i dvaletilstand med en timeout-periode på 5 sekunder; output vil være:

TIMED_WAITING

3.6. Afsluttet

Dette er tilstanden af ​​en død tråd. Det er i AFSLUTTET angive, hvornår den enten er færdig med udførelsen eller blev annulleret unormalt.

Vi har en dedikeret artikel, der diskuterer forskellige måder at stoppe tråden på.

Lad os prøve at opnå denne tilstand 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 (); // Den følgende søvnmetode giver tid nok til, at // tråd t1 kan gennemføre Thread.sleep (1000); Log.info (t1.getState ()); } @Override public void run () {// Ingen behandling i denne blok}}

Her, mens vi har startet tråden t1, den næste erklæring Thread.sleep (1000) giver tid nok til t1 at fuldføre, og så giver dette program os output som:

AFSLUTTET

Ud over trådtilstanden kan vi kontrollere er i live() metode til at afgøre, om tråden er i live eller ej. For eksempel, hvis vi kalder er i live() metode på denne tråd:

Assert.assertFalse (t1.isAlive ());

Det vender tilbage falsk. Enkelt sagt, en tråd er i live, hvis og kun hvis den har blevet startet og er endnu ikke død.

4. Konklusion

I denne vejledning lærte vi om livscyklussen for en tråd i Java. Vi kiggede på alle seks stater defineret af Tråd. Stat enum og gengivet dem med hurtige eksempler.

Selvom kodestykkerne giver den samme output i næsten alle maskiner, kan vi i nogle undtagelsestilfælde få nogle forskellige output, da den nøjagtige opførsel af Thread Scheduler ikke kan bestemmes.

Og som altid er de kodestykker, der bruges her, tilgængelige på GitHub.