logo

Lebenszyklus eines Threads (Thread-Zustände)

In Java existiert ein Thread immer in einem der folgenden Zustände. Diese Staaten sind:

  1. Neu
  2. Aktiv
  3. Blockiert / Warten
  4. Zeitgesteuertes Warten
  5. Beendet

Erläuterung verschiedener Thread-Zustände

Neu: Immer wenn ein neuer Thread erstellt wird, befindet er sich immer im neuen Zustand. Für einen Thread im neuen Status wurde der Code noch nicht ausgeführt und seine Ausführung hat daher noch nicht begonnen.

Aktiv: Wenn ein Thread die start()-Methode aufruft, wechselt er vom neuen Zustand in den aktiven Zustand. Der aktive Zustand enthält zwei Zustände: einen ist lauffähig , und das andere ist läuft .

    Lauffähig:Ein Thread, der zur Ausführung bereit ist, wird dann in den ausführbaren Zustand versetzt. Im ausführbaren Zustand kann der Thread ausgeführt werden oder jederzeit zur Ausführung bereit sein. Es ist die Aufgabe des Thread-Schedulers, dem Thread Zeit zum Ausführen bereitzustellen, d. h. den Thread in den Ausführungszustand zu versetzen.
    Ein Programm, das Multithreading implementiert, erhält für jeden einzelnen Thread eine feste Zeitspanne. Jeder einzelne Thread läuft für eine kurze Zeitspanne, und wenn die zugewiesene Zeitspanne abgelaufen ist, gibt der Thread die CPU freiwillig an den anderen Thread ab, sodass die anderen Threads ebenfalls für ihre Zeitspanne ausgeführt werden können. Wann immer ein solches Szenario auftritt, befinden sich alle Threads, die zur Ausführung bereit sind und darauf warten, dass sie an die Reihe kommen, im ausführbaren Zustand. Im ausführbaren Zustand gibt es eine Warteschlange, in der die Threads liegen.Läuft:Wenn der Thread die CPU erhält, wechselt er vom ausführbaren in den laufenden Zustand. Im Allgemeinen erfolgt die häufigste Änderung des Status eines Threads von „ausführbar“ zu „ausführbar“ und wieder zurück zu „ausführbar“.

Blockiert oder wartend: Wenn ein Thread für einen bestimmten Zeitraum (nicht dauerhaft) inaktiv ist, befindet sich der Thread entweder im blockierten Zustand oder im Wartezustand.

Beispielsweise möchte ein Thread (sagen wir, sein Name ist A) einige Daten vom Drucker drucken. Gleichzeitig verwendet jedoch der andere Thread (sagen wir, sein Name ist B) den Drucker, um einige Daten zu drucken. Daher muss Thread A warten, bis Thread B den Drucker verwendet. Somit befindet sich Thread A im blockierten Zustand. Ein Thread im blockierten Zustand kann keine Ausführung durchführen und verbraucht daher niemals einen Zyklus der Zentraleinheit (CPU). Daher können wir sagen, dass Thread A im Leerlauf bleibt, bis der Thread-Scheduler Thread A reaktiviert, der sich im Warte- oder Blockierungszustand befindet.

Wenn der Hauptthread dann die Methode join() aufruft, heißt es, dass sich der Hauptthread im Wartezustand befindet. Der Hauptthread wartet dann darauf, dass die untergeordneten Threads ihre Aufgaben abschließen. Wenn die untergeordneten Threads ihre Arbeit abschließen, wird eine Benachrichtigung an den Hauptthread gesendet, der den Thread wieder vom Wartezustand in den aktiven Zustand versetzt.

Wenn sich viele Threads im Warte- oder Blockierungszustand befinden, ist es die Pflicht des Thread-Schedulers, zu bestimmen, welcher Thread ausgewählt und welcher abgelehnt werden soll, und dem ausgewählten Thread wird dann die Möglichkeit gegeben, ausgeführt zu werden.

Zeitgesteuertes Warten: Manchmal führt das Warten zum Verhungern. Beispielsweise hat ein Thread (sein Name ist A) den kritischen Abschnitt eines Codes betreten und ist nicht bereit, diesen kritischen Abschnitt zu verlassen. In einem solchen Szenario muss ein anderer Thread (sein Name ist B) ewig warten, was zum Verhungern führt. Um ein solches Szenario zu vermeiden, wird Thread B ein zeitgesteuerter Wartezustand zugewiesen. Somit bleibt der Thread für eine bestimmte Zeitspanne und nicht für immer im Wartezustand. Ein echtes Beispiel für zeitgesteuertes Warten ist, wenn wir die Methode „sleep()“ für einen bestimmten Thread aufrufen. Die Methode „sleep()“ versetzt den Thread in den zeitgesteuerten Wartezustand. Nach Ablauf der Zeit wacht der Thread auf und beginnt mit der Ausführung an dem Punkt, an dem er ihn zuvor verlassen hat.

Beendet: Ein Thread erreicht den Beendigungsstatus aus folgenden Gründen:

  • Wenn ein Thread seine Arbeit beendet hat, existiert er oder wird normal beendet.
  • Ungewöhnliche Beendigung:Es tritt bei ungewöhnlichen Ereignissen wie einer nicht behandelten Ausnahme oder einem Segmentierungsfehler auf.

Ein beendeter Thread bedeutet, dass der Thread nicht mehr im System ist. Mit anderen Worten: Der Thread ist tot und es gibt keine Möglichkeit, den toten Thread erneut zu starten (aktiv nach dem Beenden).

Das folgende Diagramm zeigt die verschiedenen Zustände im Lebenszyklus eines Threads.

Lebenszyklus eines Java-Threads

Implementierung von Thread-Zuständen

In Java kann man den aktuellen Status eines Threads mithilfe von abrufen Thread.getState() Methode. Der java.lang.Thread.State Die Java-Klasse stellt die Konstanten ENUM bereit, um den Status eines Threads darzustellen. Diese Konstanten sind:

Linkliste in Java
 public static final Thread.State NEW 

Es stellt den ersten Zustand eines Threads dar, der der NEUE-Zustand ist.

 public static final Thread.State RUNNABLE 

Es stellt den ausführbaren Zustand dar. Es bedeutet, dass ein Thread in der Warteschlange auf die Ausführung wartet.

 public static final Thread.State BLOCKED 

Es repräsentiert den blockierten Zustand. In diesem Zustand wartet der Thread darauf, eine Sperre zu erhalten.

 public static final Thread.State WAITING 

Es stellt den Wartezustand dar. Ein Thread wechselt in diesen Zustand, wenn er die Methode Object.wait() oder die Methode Thread.join() ohne Zeitüberschreitung aufruft. Ein Thread im Wartezustand wartet darauf, dass ein anderer Thread seine Aufgabe abschließt.

 public static final Thread.State TIMED_WAITING 

Es repräsentiert den zeitgesteuerten Wartezustand. Der Hauptunterschied zwischen Warten und zeitgesteuertem Warten besteht in der Zeitbeschränkung. Beim Warten gibt es keine Zeitbeschränkung, während beim zeitgesteuerten Warten eine Zeitbeschränkung gilt. Ein Thread, der die folgende Methode aufruft, erreicht den zeitgesteuerten Wartezustand.

  • schlafen
  • Mit Timeout beitreten
  • Warte mit Timeout
  • parkUntil
  • parkNanos
 public static final Thread.State TERMINATED 

Es stellt den Endzustand eines Threads dar, der beendet oder tot ist. Ein beendeter Thread bedeutet, dass die Ausführung abgeschlossen ist.

Java-Programm zur Demonstration von Thread-Zuständen

Das folgende Java-Programm zeigt einige der Zustände eines oben definierten Threads.

Dateiname: 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()); } } 

Ausgabe:

 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 

Erläuterung: Immer wenn wir einen neuen Thread erzeugen, erhält dieser Thread den neuen Status. Wenn die Methode start() für einen Thread aufgerufen wird, versetzt der Thread-Scheduler diesen Thread in den ausführbaren Zustand. Immer wenn die Methode „join()“ für eine Thread-Instanz aufgerufen wird, muss der aktuelle Thread, der diese Anweisung ausführt, warten, bis dieser Thread seine Ausführung beendet, d. h. diesen Thread in den beendeten Zustand versetzt. Bevor die endgültige Druckanweisung auf der Konsole ausgegeben wird, ruft das Programm daher die Methode join() für Thread t2 auf, wodurch Thread t1 wartet, während Thread t2 seine Ausführung beendet und Thread t2 somit in den beendeten oder toten Zustand gelangt . Thread t1 wechselt in den Wartezustand, da er darauf wartet, dass Thread t2 seine Ausführung beendet, da er die Methode „join()“ für Thread t2 aufgerufen hat.