V Javě vlákno vždy existuje v kterémkoli z následujících stavů. Tyto stavy jsou:
- Nový
- Aktivní
- Blokováno / Čeká
- Časované čekání
- Ukončeno
Vysvětlení různých stavů vláken
Nový: Kdykoli je vytvořeno nové vlákno, je vždy v novém stavu. Pro vlákno v novém stavu nebyl kód ještě spuštěn, a proto nezačal s jeho prováděním.
Aktivní: Když vlákno vyvolá metodu start(), přesune se z nového stavu do aktivního stavu. Aktivní stav obsahuje dva stavy: jeden je spustitelný a další je běh .
Program implementující multithreading získává pevný úsek času pro každé jednotlivé vlákno. Každé vlákno běží po krátkou dobu, a když tento přidělený časový úsek skončí, vlákno dobrovolně přenechá CPU druhému vláknu, takže ostatní vlákna mohou také běžet po svůj úsek času. Kdykoli dojde k takovému scénáři, všechna vlákna, která jsou ochotna běžet a čekají, až na ně přijde řada, leží v spustitelném stavu. V spustitelném stavu existuje fronta, kde leží vlákna.
Blokováno nebo čekání: Kdykoli je vlákno po určitou dobu neaktivní (nikoli trvale), pak je vlákno buď v blokovaném stavu, nebo ve stavu čekání.
Například vlákno (řekněme, že jeho název je A) může chtít vytisknout některá data z tiskárny. Současně však druhé vlákno (řekněme, že se jmenuje B) používá tiskárnu k tisku některých dat. Proto vlákno A musí počkat, až vlákno B použije tiskárnu. Vlákno A je tedy v zablokovaném stavu. Vlákno v zablokovaném stavu není schopno provést žádné spuštění, a proto nikdy nespotřebuje žádný cyklus centrální procesorové jednotky (CPU). Můžeme tedy říci, že vlákno A zůstává nečinné, dokud plánovač vláken znovu neaktivuje vlákno A, které je ve stavu čekání nebo blokování.
Když pak hlavní vlákno vyvolá metodu join(), říká se, že hlavní vlákno je ve stavu čekání. Hlavní vlákno pak čeká, až podřízená vlákna dokončí své úkoly. Když podřízená vlákna dokončí svou úlohu, hlavnímu vláknu se odešle oznámení, které vlákno opět přesune z čekání do aktivního stavu.
Pokud je ve stavu čekání nebo blokování mnoho vláken, pak je povinností plánovače vláken určit, které vlákno zvolit a které odmítnout, a zvolené vlákno pak dostane příležitost ke spuštění.
Časované čekání: Někdy čekání vede k hladovění. Například vlákno (jeho jméno je A) vstoupilo do kritické části kódu a nechce tuto kritickou sekci opustit. V takovém scénáři musí další vlákno (jmenuje se B) čekat navždy, což vede k hladovění. Aby se předešlo takovému scénáři, je vláknu B dán stav časovaného čekání. Vlákno tedy leží ve stavu čekání po určitou dobu a ne navždy. Skutečným příkladem časovaného čekání je, když vyvoláme metodu sleep() na konkrétním vláknu. Metoda sleep() uvede vlákno do stavu časovaného čekání. Po vypršení času se vlákno probudí a spustí se od okamžiku, kdy dříve odešlo.
Ukončeno: Vlákno dosáhne stavu ukončení z následujících důvodů:
- Když vlákno dokončí svou úlohu, existuje nebo se normálně ukončí.
Ukončené vlákno znamená, že vlákno již není v systému. Jinými slovy, vlákno je mrtvé a neexistuje způsob, jak se mrtvé vlákno znovu spustit (aktivní po zabití).
Následující diagram ukazuje různé stavy zahrnuté v životním cyklu vlákna.
Implementace stavů vláken
V Javě lze získat aktuální stav vlákna pomocí Thread.getState() metoda. The java.lang.Thread.State třída Java poskytuje konstanty ENUM, které reprezentují stav vlákna. Tyto konstanty jsou:
seznam vytváření java
public static final Thread.State NEW
Představuje první stav vlákna, který je NEW stavem.
public static final Thread.State RUNNABLE
Představuje spustitelný stav. Znamená to, že vlákno čeká ve frontě na spuštění.
public static final Thread.State BLOCKED
Představuje blokovaný stav. V tomto stavu vlákno čeká na získání zámku.
public static final Thread.State WAITING
Představuje stav čekání. Vlákno přejde do tohoto stavu, když vyvolá metodu Object.wait() nebo Thread.join() bez časového limitu. Vlákno ve stavu čekání čeká, až jiné vlákno dokončí svůj úkol.
public static final Thread.State TIMED_WAITING
Představuje stav časovaného čekání. Hlavním rozdílem mezi čekáním a časovaným čekáním je časové omezení. Čekání nemá žádné časové omezení, zatímco časované čekání má časové omezení. Vlákno vyvolávající následující metodu dosáhne stavu časovaného čekání.
- spát
- připojit se s časovým limitem
- čekat s časovým limitem
- parkDokud
- parkNanos
public static final Thread.State TERMINATED
Představuje konečný stav vlákna, které je ukončeno nebo mrtvé. Ukončené vlákno znamená, že dokončilo své provádění.
Program Java pro demonstraci stavů vláken
Následující program Java ukazuje některé stavy vlákna definovaného výše.
Název souboru: 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()); } }
Výstup:
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
Vysvětlení: Kdykoli vytvoříme nové vlákno, toto vlákno dosáhne nového stavu. Když je na vlákně vyvolána metoda start(), plánovač vláken přesune toto vlákno do spustitelného stavu. Kdykoli je v jakékoli instanci vlákna vyvolána metoda join(), aktuální vlákno provádějící tento příkaz musí počkat, až toto vlákno dokončí své provádění, tj. přesunout vlákno do stavu ukončení. Proto před vytištěním konečného tiskového příkazu na konzole program vyvolá metodu join() na vlákně t2, čímž nechá vlákno t1 čekat, dokud vlákno t2 dokončí své provádění, a tak se vlákno t2 dostane do ukončeného nebo mrtvého stavu. . Vlákno t1 přejde do stavu čekání, protože čeká, až vlákno t2 dokončí své provádění, protože vyvolalo metodu join() ve vláknu t2.