Životný cyklus vlákna v Jave

1. Úvod

V tomto článku si podrobne rozoberieme základný koncept v Jave - životný cyklus vlákna.

Na lepšie pochopenie týchto stavov počas vykonávania vlákna použijeme rýchly ilustrovaný diagram a samozrejme praktické útržky kódu.

Ak chcete začať rozumieť vláknam v Jave, je dobré začať týmto článkom o vytváraní vlákna.

2. Multithreading v Jave

V jazyku Java je multithreading riadený základným konceptom vlákna. Počas svojho životného cyklu vlákna prechádzajú rôznymi stavmi:

3. Životný cyklus vlákna v Jave

The java.lang.Thread trieda obsahuje a statický stavový výčet - ktorá definuje jej potenciálne stavy. V priebehu daného časového obdobia môže byť vlákno iba v jednom z týchto stavov:

  1. NOVÝ - novo vytvorené vlákno, ktoré ešte nezačalo s realizáciou
  2. BEŽNÉ - buď beží, alebo je pripravený na vykonanie, ale čaká na pridelenie prostriedkov
  3. ZABLOKOVANÉ - čakanie na získanie zámku monitora na zadanie alebo opätovné zadanie synchronizovaného bloku / metódy
  4. ČAKANIE - čakanie na vykonanie konkrétnej akcie iným vláknom bez časového obmedzenia
  5. TIMED_WAITING - čakanie na to, aby nejaké iné vlákno vykonalo konkrétnu akciu počas stanoveného obdobia
  6. UKONČENÝ - dokončil svoju realizáciu

Všetky tieto stavy sú obsiahnuté v diagrame vyššie; poďme si teraz podrobne rozobrať každú z nich.

3.1. Nový

A NOVÝZávit (alebo Born Závit) je vlákno, ktoré bolo vytvorené, ale ešte nebolo spustené. V tomto stave zostáva, kým ho nezačneme používať štart () metóda.

Nasledujúci úryvok kódu zobrazuje novovytvorené vlákno, ktoré sa nachádza v priečinku NOVÝ štát:

Spustiteľný Spustiteľný súbor = nový NewState (); Vlákno t = nové vlákno (spustiteľné); Log.info (t.getState ());

Pretože sme nezačali spomínané vlákno, metóda t.getState () výtlačky:

NOVÝ

3.2. Spustiteľné

Keď sme vytvorili nové vlákno a nazvali sme ho štart () metóda je presunutá z NOVÝ do BEŽNÉ štát. Vlákna v tomto stave sú buď spustené, alebo pripravené na spustenie, čakajú však na pridelenie prostriedkov zo systému.

V prostredí s viacerými vláknami vyhradzuje Plánovač vlákien (ktorý je súčasťou JVM) každému vláknu pevne stanovený čas. Takže to beží určitý čas, potom sa vzdá kontroly iným BEŽNÉ nite.

Napríklad pridajme t.start () metódu na náš predchádzajúci kód a pokúsiť sa získať prístup k jeho aktuálnemu stavu:

Spustiteľný Spustiteľný súbor = nový NewState (); Vlákno t = nové vlákno (spustiteľné); t.start (); Log.info (t.getState ());

Tento kód je pravdepodobne vrátiť výstup ako:

BEŽNÉ

Upozorňujeme, že v tomto príklade nie je vždy zaručené, že kým dosiahne naša kontrola t.getState (), bude stále v BEŽNÉ štát.

Môže sa stať, že to bol okamžite naplánovaný Plánovač vlákien a môže dokončiť popravu. V takýchto prípadoch môžeme získať iný výstup.

3.3. Zablokované

Vlákno je v ZABLOKOVANÉ stav, kedy momentálne nie je spôsobilý na spustenie. Do tohto stavu sa dostane, keď čaká na uzamknutie monitora, a pokúša sa získať prístup k časti kódu, ktorá je uzamknutá iným vláknom.

Pokúsme sa reprodukovať tento stav:

public class BlockedState {public static void main (String [] args) throws InterruptedException {Thread t1 = new Thread (new DemoThreadB ()); Vlákno t2 = nové vlákno (nové DemoThreadB ()); t1.start (); t2.start (); Závit. Spánok (1 000); Log.info (t2.getState ()); System.exit (0); }} trieda DemoThreadB implementuje Runnable {@Override public void run () {commonResource (); } verejné statické synchronizované void commonResource () {while (true) {// Nekonečná slučka napodobňujúca náročné spracovanie // 't1' neopustí túto metódu // keď 't2' sa pokúsi zadať toto}}}

V tomto kóde:

  1. Vytvorili sme dve rôzne vlákna - t1 a t2
  2. t1 sa spustí a vstúpi do synchronizovaného commonResource () metóda; to znamená, že k nej má prístup iba jedno vlákno; všetky ďalšie nasledujúce vlákna, ktoré sa pokúsia získať prístup k tejto metóde, budú blokované z ďalšieho vykonávania, kým súčasné dokončí spracovanie
  3. Kedy t1 zadá túto metódu, je uchovaná v nekonečnej slučke while; toto má iba napodobniť náročné spracovanie, aby všetky ostatné vlákna nemohli vstúpiť do tejto metódy
  4. Teraz, keď začneme t2, pokúša sa vstúpiť do commonResource () metóda, ku ktorej už pristupuje t1, teda t2 budú uchovávané v ZABLOKOVANÉ štát

Byť v tomto stave, voláme t2.getState () a získajte výstup ako:

ZABLOKOVANÉ

3.4. Čaká sa

Niť je v ČAKANIE stav, keď čaká na vykonanie konkrétnej akcie iným vláknom. Podľa JavaDocs môže každé vlákno vstúpiť do tohto stavu volaním ktorejkoľvek z nasledujúcich troch metód:

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

Všimnite si, že v počkaj () a pripojiť sa () - nedefinujeme žiadne časové obdobie, pretože scenáru sa venuje ďalšia časť.

Máme samostatný tutoriál, ktorý podrobne pojednáva o použití počkaj (), upozorniť () a notifyAll ().

Pokúsme sa zatiaľ reprodukovať tento stav:

verejná trieda WaitingState implementuje 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 (); skúste {t2.join (); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); Log.error ("Vlákno prerušené", e); }}} trieda DemoThreadWS implementuje Runnable {public void run () {try {Thread.sleep (1000); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); Log.error ("Vlákno prerušené", e); } Log.info (WaitingState.t1.getState ()); }}

Poďme diskutovať o tom, čo tu robíme:

  1. Vytvorili sme a začali sme t1
  2. t1 vytvára a t2 a spustí to
  3. Zatiaľ čo spracovanie t2 pokračuje, voláme t2.join (), toto kladie t1 v ČAKANIE štát do t2 dokončil exekúciu
  4. Odkedy t1 čaká na t2 na doplnenie voláme t1.getState () od t2

Výstup je tu, ako by ste čakali:

ČAKANIE

3.5. Časované čakanie

Niť je v TIMED_WAITING stav, keď čaká na ďalšie vlákno, aby vykonalo konkrétnu akciu v stanovenom čase.

Podľa JavaDocs existuje päť spôsobov, ako navliecť vlákno TIMED_WAITING štát:

  1. závit. spánok (dlhé milis)
  2. počkať (časový limit int) alebo počkať (int timeout, int nanos)
  3. thread.join (dlhé millis)
  4. LockSupport.parkNanos
  5. LockSupport.parkUž

Ak si chcete prečítať viac o rozdieloch medzi počkaj () a spánok () v Jave, pozrite si tento špecializovaný článok tu.

Pokúsme sa zatiaľ tento stav rýchlo reprodukovať:

public class TimedWaitingState {public static void main (String [] args) hodí InterruptedException {DemoThread obj1 = new DemoThread (); Vlákno t1 = nové vlákno (obj1); t1.start (); // Nasledujúci spánok poskytne ThreadScheduleru // dostatok času na začatie spracovania vlákna t1 Thread.sleep (1000); Log.info (t1.getState ()); }} trieda DemoThread implementuje Runnable {@Override public void run () {try {Thread.sleep (5000); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); Log.error ("Vlákno prerušené", e); }}}

Tu sme vytvorili a založili vlákno t1 ktorý je uvedený do režimu spánku s časovým limitom 5 sekúnd; výstup bude:

TIMED_WAITING

3.6. Ukončené

Toto je stav mŕtveho vlákna. Je to v UKONČENÝ stav, keď buď ukončil vykonávanie, alebo bol neobvykle ukončený.

Máme vyhradený článok, ktorý pojednáva o rôznych spôsoboch zastavenia vlákna.

Pokúsme sa tento stav dosiahnuť v nasledujúcom príklade:

verejná trieda TerminatedState implementuje Runnable {public static void main (String [] args) hodí InterruptedException {Thread t1 = new Thread (new TerminatedState ()); t1.start (); // Nasledujúca metóda spánku poskytne dostatok času // vláknu t1 na dokončenie Thread.sleep (1000); Log.info (t1.getState ()); } @Override public void run () {// V tomto bloku nie je spracované}}

Tu, zatiaľ čo sme začali vlákno t1, ďalšie vyjadrenie Závit. Spánok (1 000) dáva dostatok času na t1 dokončiť, a tak nám tento program poskytne výstup ako:

UKONČENÝ

Okrem stavu vlákna môžeme skontrolovať je nažive() metóda na určenie, či je vlákno živé alebo nie. Napríklad, ak hovoríme je nažive() metóda v tomto vlákne:

Assert.assertFalse (t1.isAlive ());

Vracia sa to nepravdivé. Zjednodušene povedané, vlákno je živé, len ak má bola zahájená a ešte nezomrela.

4. Záver

V tomto tutoriáli sme sa dozvedeli o životnom cykle vlákna v Jave. Pozreli sme sa na všetkých šesť štátov definovaných Závit. Štát vymenovať a reprodukovať ich pomocou rýchlych príkladov.

Aj keď úryvky kódu poskytnú rovnaký výstup takmer na každom stroji, vo výnimočných prípadoch môžeme získať rôzne výstupy, pretože nie je možné určiť presné správanie plánovača vlákien.

A ako vždy, tu použité útržky kódu sú k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found