logo

Levenscyclus van een draad (draadstatussen)

In Java bestaat een thread altijd in een van de volgende statussen. Deze staten zijn:

  1. Nieuw
  2. Actief
  3. Geblokkeerd / Wachten
  4. Getimed wachten
  5. Beëindigd

Uitleg van verschillende threadstatussen

Nieuw: Wanneer een nieuwe thread wordt aangemaakt, heeft deze altijd de nieuwe status. Voor een thread in de nieuwe status is de code nog niet uitgevoerd en dus nog niet begonnen met de uitvoering ervan.

Actief: Wanneer een thread de methode start() aanroept, gaat deze van de nieuwe status naar de actieve status. De actieve toestand bevat twee toestanden: één is uitvoerbaar , en de andere is rennen .

    Uitvoerbaar:Een thread die klaar is om te worden uitgevoerd, wordt vervolgens naar de uitvoerbare status verplaatst. In de uitvoerbare status kan de thread actief zijn of op een bepaald tijdstip gereed zijn om te worden uitgevoerd. Het is de taak van de threadplanner om de threadtijd te geven om te worden uitgevoerd, d.w.z. de thread naar de actieve status te verplaatsen.
    Een programma dat multithreading implementeert, krijgt een vast tijdsdeel voor elke individuele thread. Elke thread draait een korte tijdsperiode en wanneer dat toegewezen tijdsdeel voorbij is, geeft de thread vrijwillig de CPU af aan de andere thread, zodat de andere threads ook hun tijdsdeel kunnen draaien. Wanneer een dergelijk scenario zich voordoet, bevinden al die threads die bereid zijn te worden uitgevoerd, wachtend op hun beurt om te worden uitgevoerd, zich in de uitvoerbare staat. In de uitvoerbare staat is er een wachtrij waar de threads liggen.Rennen:Wanneer de thread de CPU krijgt, gaat deze van de uitvoerbare naar de actieve status. Over het algemeen is de meest voorkomende verandering in de status van een thread van uitvoerbaar naar actief en weer terug naar uitvoerbaar.

Geblokkeerd of wachtend: Wanneer een thread enige tijd inactief is (niet permanent), bevindt de thread zich in de geblokkeerde status of bevindt deze zich in de wachtstatus.

Een thread (laten we zeggen dat de naam A is) wil bijvoorbeeld bepaalde gegevens van de printer afdrukken. Tegelijkertijd gebruikt de andere thread (laten we zeggen dat de naam B is) echter de printer om bepaalde gegevens af te drukken. Daarom moet draad A wachten totdat draad B de printer gebruikt. Thread A bevindt zich dus in de geblokkeerde toestand. Een thread in de geblokkeerde status kan geen enkele uitvoering uitvoeren en verbruikt dus nooit een cyclus van de Central Processing Unit (CPU). We kunnen dus zeggen dat thread A inactief blijft totdat de threadplanner thread A opnieuw activeert, die zich in de wachtende of geblokkeerde status bevindt.

Wanneer de hoofdthread de methode join() aanroept, wordt er gezegd dat de hoofdthread zich in de wachtstatus bevindt. De hoofdthread wacht vervolgens tot de onderliggende threads hun taken hebben voltooid. Wanneer de onderliggende threads hun taak voltooien, wordt er een melding naar de hoofdthread verzonden, waardoor de thread opnieuw van de wachtstand naar de actieve status wordt verplaatst.

Als er veel threads in de wacht- of geblokkeerde status zijn, is het de taak van de threadplanner om te bepalen welke thread moet worden gekozen en welke moet worden afgewezen, en de gekozen thread krijgt dan de kans om te worden uitgevoerd.

Getimed wachten: Soms leidt wachten tot verhongering. Een thread (de naam is A) is bijvoorbeeld het kritieke gedeelte van een code binnengegaan en wil dat kritieke gedeelte niet verlaten. In een dergelijk scenario moet een andere draad (de naam is B) voor altijd wachten, wat tot hongersnood leidt. Om een ​​dergelijk scenario te voorkomen, wordt een getimede wachtstatus gegeven aan thread B. De thread blijft dus gedurende een specifieke tijdsduur in de wachtstatus, en niet voor altijd. Een echt voorbeeld van getimed wachten is wanneer we de methode sleep() aanroepen voor een specifieke thread. De methode sleep() plaatst de thread in de getimede wachtstatus. Nadat de tijd om is, wordt de thread wakker en begint de uitvoering vanaf het moment waarop deze eerder is vertrokken.

Beëindigd: Een thread bereikt de beëindigingsstatus vanwege de volgende redenen:

  • Wanneer een thread zijn taak heeft voltooid, bestaat deze of eindigt deze normaal.
  • Abnormale beëindiging:Het treedt op bij ongebruikelijke gebeurtenissen, zoals een onverwerkte uitzondering of een segmentatiefout.

Een beëindigde thread betekent dat de thread niet meer in het systeem aanwezig is. Met andere woorden, de thread is dood en er is geen manier om de dode thread opnieuw te activeren (actief na het doden).

Het volgende diagram toont de verschillende toestanden die betrokken zijn bij de levenscyclus van een thread.

Levenscyclus van Java-threads

Implementatie van Thread-staten

In Java kan men de huidige status van een thread verkrijgen met behulp van de Thread.getState() methode. De java.lang.Thread.State klasse van Java biedt de constanten ENUM om de status van een thread weer te geven. Deze constanten zijn:

java-string join
 public static final Thread.State NEW 

Het vertegenwoordigt de eerste status van een thread die de NIEUWE status is.

 public static final Thread.State RUNNABLE 

Het vertegenwoordigt de uitvoerbare status. Het betekent dat een thread in de wachtrij wacht om te worden uitgevoerd.

 public static final Thread.State BLOCKED 

Het vertegenwoordigt de geblokkeerde staat. In deze staat wacht de thread op een vergrendeling.

 public static final Thread.State WAITING 

Het vertegenwoordigt de wachtstaat. Een thread krijgt deze status wanneer deze de methode Object.wait() of de methode Thread.join() zonder time-out aanroept. Een thread in de wachtstatus wacht totdat een andere thread zijn taak heeft voltooid.

 public static final Thread.State TIMED_WAITING 

Het vertegenwoordigt de getimede wachtstatus. Het belangrijkste verschil tussen wachten en getimed wachten is de tijdsbeperking. Wachten heeft geen tijdsbeperking, terwijl getimed wachten wel tijdsbeperking heeft. Een thread die de volgende methode aanroept, bereikt de getimede wachtstatus.

  • slaap
  • meedoen met time-out
  • wacht met time-out
  • parkTot
  • parkNanos
 public static final Thread.State TERMINATED 

Het vertegenwoordigt de eindstatus van een thread die is beëindigd of dood is. Een beëindigde thread betekent dat de uitvoering ervan is voltooid.

Java-programma voor het demonstreren van threadstatussen

Het volgende Java-programma toont enkele van de statussen van een hierboven gedefinieerde thread.

Bestandsnaam: ThreadState.java

 // ABC class implements the interface Runnable class ABC implements Runnable { public void run() { // try-catch block try { // moving thread t2 to the state timed waiting Thread.sleep(100); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t1 while it invoked the method join() on thread t2 -'+ ThreadState.t1.getState()); // try-catch block try { Thread.sleep(200); } catch (InterruptedException ie) { ie.printStackTrace(); } } } // ThreadState class implements the interface Runnable public class ThreadState implements Runnable { public static Thread t1; public static ThreadState obj; // main method public static void main(String argvs[]) { // creating an object of the class ThreadState obj = new ThreadState(); t1 = new Thread(obj); // thread t1 is spawned // The thread t1 is currently in the NEW state. System.out.println('The state of thread t1 after spawning it - ' + t1.getState()); // invoking the start() method on // the thread t1 t1.start(); // thread t1 is moved to the Runnable state System.out.println('The state of thread t1 after invoking the method start() on it - ' + t1.getState()); } public void run() { ABC myObj = new ABC(); Thread t2 = new Thread(myObj); // thread t2 is created and is currently in the NEW state. System.out.println('The state of thread t2 after spawning it - '+ t2.getState()); t2.start(); // thread t2 is moved to the runnable state System.out.println('the state of thread t2 after calling the method start() on it - ' + t2.getState()); // try-catch block for the smooth flow of the program try { // moving the thread t1 to the state timed waiting Thread.sleep(200); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t2 after invoking the method sleep() on it - '+ t2.getState() ); // try-catch block for the smooth flow of the program try { // waiting for thread t2 to complete its execution t2.join(); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t2 when it has completed it's execution - ' + t2.getState()); } } 

Uitgang:

 The state of thread t1 after spawning it - NEW The state of thread t1 after invoking the method start() on it - RUNNABLE The state of thread t2 after spawning it - NEW the state of thread t2 after calling the method start() on it - RUNNABLE The state of thread t1 while it invoked the method join() on thread t2 -TIMED_WAITING The state of thread t2 after invoking the method sleep() on it - TIMED_WAITING The state of thread t2 when it has completed it's execution - TERMINATED 

Uitleg: Telkens wanneer we een nieuwe draad voortbrengen, bereikt die draad de nieuwe staat. Wanneer de methode start() wordt aangeroepen voor een thread, verplaatst de threadplanner die thread naar de uitvoerbare status. Telkens wanneer de methode join() wordt aangeroepen op een threadinstantie, moet de huidige thread die die instructie uitvoert, wachten tot deze thread zijn uitvoering heeft voltooid, dat wil zeggen, die thread naar de beëindigde status verplaatst. Voordat de laatste print-instructie op de console wordt afgedrukt, roept het programma daarom de methode join() op thread t2 aan, waardoor de thread t1 wacht terwijl de thread t2 zijn uitvoering voltooit en de thread t2 dus in de beëindigde of dode toestand terechtkomt. . Thread t1 gaat naar de wachtstatus omdat het wacht tot thread t2 zijn uitvoering voltooit, omdat het de methode join() op thread t2 heeft aangeroepen.