Programovanie

Java 101: Pochopenie vlákien Java, Časť 4: Skupiny vlákien, volatilita a miestne premenné premenných

Tento mesiac Java 101 uzatvára sériu vlákien zameraním na skupiny vlákien, volatilitu, lokálne premenné vlákna, časovače a ThreadDeath trieda.

Pochopenie vlákien Java - prečítajte si celú sériu

  • Časť 1: Predstavujeme vlákna a spustiteľné súbory
  • Časť 2: Synchronizácia vlákna
  • Časť 3: Plánovanie vlákna, čakanie / upozornenie a prerušenie vlákna
  • Časť 4: Skupiny vlákien, volatilita, miestne premenné vlákna, časovače a smrť vlákna

Skupiny vlákien

V programe sieťového servera jedno vlákno čaká na a prijíma požiadavky z klientských programov na vykonávanie napríklad databázových transakcií alebo zložitých výpočtov. Vlákno zvyčajne vytvorí nové vlákno na vybavenie žiadosti. V závislosti od objemu požiadavky môže byť súčasne prítomných veľa rôznych vlákien, čo komplikuje správu vlákien. Na zjednodušenie správy vlákien si programy organizujú svoje vlákna pomocou skupiny vlákienjava.lang.ThreadGroup objekty, ktoré zoskupujú súvisiace vlákna ' Závit (a Závit podtrieda) objekty. Váš program môže napríklad použiť ThreadGroup zoskupiť všetky tlačové vlákna do jednej skupiny.

Poznámka: Aby bola diskusia jednoduchá, odkazujem na skupiny vlákien, akoby organizovali vlákna. V skutočnosti sa skupiny vlákien organizujú Závit (a Závit podtrieda) objekty spojené s vláknami.

Java vyžaduje každé vlákno a každú skupinu vlákien - uložte skupinu koreňových vlákien, systém- pripojiť sa k inej skupine vlákien. Toto usporiadanie vedie k hierarchickej štruktúre skupín vlákien, ktorú obrázok nižšie ilustruje v kontexte aplikácie.

V hornej časti štruktúry figúry je systém skupina vlákien. Vytvorené JVM systém skupina organizuje vlákna JVM, ktoré sa zaoberajú dokončovaním objektov a ďalšími systémovými úlohami, a slúži ako skupina koreňových vlákien v hierarchickej štruktúre skupín vlákien aplikácie. Rovno pod systém je vytvorený JVM hlavný skupina vlákien, ktorá je systémskupina podvlákna (skrátene podskupina). hlavný obsahuje najmenej jedno vlákno - hlavné vlákno vytvorené JVM, ktoré vykonáva pokyny v bajtovom kóde v hlavný() metóda.

Pod hlavný skupina býva podskupina 1 a podskupina 2 podskupiny, podskupiny vytvorené aplikáciou (ktoré aplikácia figúry vytvára). Ďalej podskupina 1 zoskupuje tri vlákna vytvorené aplikáciou: závit 1, závit 2a závit 3. Naproti tomu podskupina 2 zoskupuje jedno vlákno vytvorené aplikáciou: moje vlákno.

Teraz, keď už ovládate základné veci, začnime vytvárať skupiny vlákien.

Vytvorte skupiny vlákien a priraďte vlákna k týmto skupinám

The ThreadGroup Dokumentácia triedy SDK odhaľuje dvoch konštruktérov: ThreadGroup (názov reťazca) a ThreadGroup (ThreadGroup rodič, názov reťazca). Obaja konštruktéri vytvoria skupinu vlákien a pomenujú ju ako názov parameter určuje. Konštruktéri sa líšia výberom toho, ktorá skupina vlákien slúži ako nadradená pre novovytvorenú skupinu vlákien. Každá skupina vlákien, s výnimkou systém, musí mať nadradenú skupinu vlákien. Pre ThreadGroup (názov reťazca), rodič je skupina vlákien vlákna, ktoré volá ThreadGroup (názov reťazca). Ako príklad, ak volá hlavné vlákno ThreadGroup (názov reťazca), novovytvorená skupina vlákien má ako hlavnú skupinu hlavného vlákna–hlavný. Pre ThreadGroup (ThreadGroup rodič, názov reťazca), rodič je skupina, ktorá rodič referencie. Nasledujúci kód ukazuje, ako použiť tieto konštruktory na vytvorenie dvojice skupín vlákien:

public static void main (String [] args) {ThreadGroup tg1 = new ThreadGroup ("A"); ThreadGroup tg2 = nová ThreadGroup (tg1, "B"); }

V kóde vyššie vytvára hlavné vlákno dve skupiny vlákien: A a B. Najskôr sa vytvorí hlavné vlákno A volaním ThreadGroup (názov reťazca). The tg1-referencovaný rodič skupiny vlákien je hlavný pretože hlavný je skupina vlákien hlavného vlákna. Po druhé, vytvorí sa hlavné vlákno B volaním ThreadGroup (ThreadGroup rodič, názov reťazca). The tg2-referencovaný rodič skupiny vlákien je A pretože tg1odkaz je argumentom pre ThreadGroup (tg1, "B") a A asociuje s tg1.

Tip: Akonáhle už nebudete potrebovať hierarchiu ThreadGroup predmety, hovor ThreadGroupje neplatné zničenie () metóda prostredníctvom odkazu na ThreadGroup objekt na vrchole tejto hierarchie. Ak vrch ThreadGroup objekt a všetky objekty podskupín neobsahujú objekty vlákien, zničiť () pripravuje tieto objekty skupín vlákien na zber odpadkov. Inak, zničiť () hodí IllegalThreadStateException objekt. Kým však anulujete odkaz na začiatok ThreadGroup objekt (za predpokladu, že premenná poľa obsahuje tento odkaz), smetiar nemôže tento objekt zhromaždiť. Podľa horného objektu môžete určiť, či bolo na telefónne číslo uskutočnené predchádzajúce volanie zničiť () metóda volaním ThreadGroupje boolean isDestroyed () metóda. Táto metóda vráti hodnotu true, ak bola zničená hierarchia skupín vlákien.

Samotné skupiny vlákien sú zbytočné. Na akékoľvek použitie musia zoskupovať vlákna. Zoskupujete vlákna do skupín vlákien tak, že ich odovzdáte ThreadGroup odkazy na príslušné Závit konštruktéri:

ThreadGroup tg = new ThreadGroup ("podskupina 2"); Vlákno t = nové vlákno (tg, "moje vlákno");

Vyššie uvedený kód najskôr vytvorí a podskupina 2 skupina s hlavný ako materská skupina. (Predpokladám, že hlavné vlákno vykoná kód.) Kód potom vytvorí a moje vláknoZávit objekt v podskupina 2 skupina.

Teraz vytvorme aplikáciu, ktorá vytvára hierarchickú štruktúru skupín vlákien našej postavy:

Zoznam 1. ThreadGroupDemo.java

// ThreadGroupDemo.java class ThreadGroupDemo {public static void main (String [] args) {ThreadGroup tg = new ThreadGroup ("subgroup 1"); Vlákno t1 = nové vlákno (tg, "vlákno 1"); Vlákno t2 = nové vlákno (tg, "vlákno 2"); Vlákno t3 = nové vlákno (tg, "vlákno 3"); tg = new ThreadGroup ("podskupina 2"); Vlákno t4 = nové vlákno (tg, "moje vlákno"); tg = Thread.currentThread () .getThreadGroup (); int agc = tg.activeGroupCount (); System.out.println ("Aktívne skupiny vlákien v skupine vlákien" + tg.getName () + ":" + agc); tg.list (); }}

ThreadGroupDemo vytvorí príslušnú skupinu vlákien a objekty vlákien na zrkadlenie toho, čo vidíte na obrázku vyššie. Preukázať, že podskupina 1 a podskupina 2 skupiny sú hlavnýsú iba podskupiny, ThreadGroupDemo robí toto:

  1. Načíta odkaz na hlavné vlákno ThreadGroup objekt zavolaním Závitje statický currentThread () metóda (ktorá vracia odkaz na hlavné vlákno Závit objekt), za ktorým nasleduje Závitje ThreadGroup getThreadGroup () metóda.
  2. Vyzýva ThreadGroupje int activeGroupCount () metóda na práve vrátený ThreadGroup referencia na vrátenie odhadu aktívnych skupín v skupine vlákien hlavného vlákna.
  3. Vyzýva ThreadGroupje Reťazec getName () metóda na vrátenie názvu skupiny vlákien hlavného vlákna.
  4. Vyzýva ThreadGroupje zoznam neplatných () metóda tlače na štandardnom výstupnom zariadení podrobnosti o skupine vlákien hlavného vlákna a všetkých podskupinách.

Pri spustení, ThreadGroupDemo zobrazí nasledujúci výstup:

Aktívne skupiny vlákien v hlavnej skupine vlákien: 2 java.lang.ThreadGroup [name = main, maxpri = 10] Thread [main, 5, main] Thread [Thread-0,5, main] java.lang.ThreadGroup [name = subgroup 1, maxpri = 10] vlákno [vlákno 1,5, podskupina 1] vlákno [vlákno 2,5, podskupina 1] vlákno [vlákno 3,5, podskupina 1] java.lang.ThreadGroup [name = podskupina 2, maxpri = 10 ] Vlákno [moje vlákno, 5, podskupina 2]

Výstup, ktorý sa začína na Závit výsledky z zoznam ()interné hovory do Závitje natiahnuť() metóda, výstupný formát, ktorý som popísal v časti 1. Spolu s týmto výstupom vidíte výstup začínajúci sa na java.lang.ThreadGroup. Tento výstup identifikuje názov skupiny vlákien, za ktorým nasleduje jeho maximálna priorita.

Prioritné skupiny a skupiny vlákien

Maximálna priorita skupiny vlákien je najvyššia priorita, ktorú môže každé z jej vlákien dosiahnuť. Zvážte vyššie uvedený program sieťových serverov. V rámci tohto programu vlákno čaká na klientske programy a prijíma ich. Predtým, ako to urobíte, vlákno wait-for / accept-request najskôr vytvorí skupinu vlákien s maximálnou prioritou tesne pod prioritou tohto vlákna. Neskôr, keď príde žiadosť, vlákno čakania na / prijatie žiadosti vytvorí nové vlákno, ktoré bude reagovať na požiadavku klienta, a pridá nové vlákno do predtým vytvorenej skupiny vlákien. Priorita nového vlákna sa automaticky zníži na maximum skupiny vlákien. Týmto spôsobom vlákno Wait for / Accept-Request reaguje na žiadosti častejšie, pretože sa spúšťa častejšie.

Java pripisuje každej skupine vlákien maximálnu prioritu. Pri vytváraní skupiny získa Java túto prioritu od svojej nadradenej skupiny. Použite ThreadGroupje void setMaxPriority (priorita int) metóda na následné nastavenie maximálnej priority. Vlákna, ktoré do skupiny pridáte po nastavení maximálnej priority, nemôžu mať prioritu presahujúcu maximum. Akékoľvek vlákno s vyššou prioritou sa automaticky zníži, keď sa stane členom skupiny vlákien. Ak však použijete setMaxPriority (priorita int) aby sa znížila maximálna priorita skupiny, všetky vlákna pridané do skupiny pred volaním tejto metódy si zachovajú svoje pôvodné priority. Napríklad ak pridáte vlákno priority 8 do skupiny s maximálnou prioritou 9 a potom znížite maximálnu prioritu tejto skupiny na 7, vlákno priority 8 zostane na priorite 8. Maximálnu prioritu skupiny vlákien môžete kedykoľvek určiť volaním ThreadGroupje int getMaxPriority () metóda. Na demonštráciu skupín priorít a vlákien som napísal MaxPriorityDemo:

Zoznam 2. MaxPriorityDemo.java

// MaxPriorityDemo.java trieda MaxPriorityDemo {public static void main (String [] args) {ThreadGroup tg = new ThreadGroup ("A"); System.out.println ("tg maximálna priorita =" + tg.getMaxPriority ()); Vlákno t1 = nové vlákno (tg, "X"); System.out.println ("priorita t1 =" + t1.getPriority ()); t1.setPriority (Thread.NORM_PRIORITY + 1); System.out.println ("priorita t1 po setPriority () =" + t1.getPriority ()); tg.setMaxPriority (Thread.NORM_PRIORITY - 1); System.out.println ("maximálna priorita tg po setMaxPriority () =" + tg.getMaxPriority ()); System.out.println ("priorita t1 po setMaxPriority () =" + t1.getPriority ()); Vlákno t2 = nové vlákno (tg, "Y"); System.out.println ("priorita t2 =" + t2.getPriority ()); t2.setPriority (Thread.NORM_PRIORITY); System.out.println ("priorita t2 po setPriority () =" + t2.getPriority ()); }}

Pri spustení, MaxPriorityDemo vytvorí nasledujúci výstup:

tg maximálna priorita = 10 t1 priorita = 5 t1 priorita po setPriority () = 6 tg maximálna priorita po setMaxPriority () = 4 t1 priorita po setMaxPriority () = 6 t2 priorita = 4 t2 priorita po setPriority () = 4

Skupina vlákien A (ktoré tg referencie) sa začína najvyššou prioritou (10) ako jej maximom. Závit X, ktorého Závit objekt t1 referencie, pripojí sa ku skupine a dostane 5 ako svoju prioritu. Zmeníme prioritu tohto vlákna na 6, ktorá bude úspešná, pretože 6 je menej ako 10. Následne zavoláme setMaxPriority (priorita int) znížiť maximálnu prioritu skupiny na 4. Aj keď vlákno X zostáva na priorite 6, ktorá je novo pridaná Y. vlákno dostane 4 ako svoju prioritu. Na záver pokus o zväčšenie vlákna Y.priorita 5 zlyhá, pretože 5 je väčšia ako 4.

Poznámka:setMaxPriority (priorita int) automaticky upravuje maximálnu prioritu podskupín skupiny vlákien.

Okrem použitia skupín vlákien na obmedzenie priority vlákien môžete vykonať ďalšie úlohy zavolaním rôznych ThreadGroup metódy, ktoré sa vzťahujú na vlákno každej skupiny. Metódy zahŕňajú void suspend (), neplatný životopis (), void stop ()a void interrupt (). Pretože spoločnosť Sun Microsystems zastarala prvé tri metódy (sú nebezpečné), preskúmame ich iba prerušiť().

Prerušte skupinu vlákien

ThreadGroupje prerušiť() metóda umožňuje vláknu prerušiť vlákna a podskupiny konkrétnej skupiny vlákien. Táto technika by sa ukázala ako vhodná v nasledujúcom scenári: Hlavné vlákno vašej aplikácie vytvára viac vlákien, z ktorých každé vykonáva jednotku práce. Pretože všetky vlákna musia dokončiť svoje príslušné pracovné jednotky, aby mohlo každé vlákno preskúmať výsledky, každé vlákno počká po dokončení svojej pracovnej jednotky. Hlavné vlákno sleduje pracovný stav. Len čo čakajú všetky ostatné vlákna, zavolá sa hlavné vlákno prerušiť() prerušiť čakanie ostatných vlákien. Potom tieto vlákna môžu preskúmať a spracovať výsledky. Výpis 3 ukazuje prerušenie skupiny vlákien:

Zoznam 3. InterruptThreadGroup.java

// InterruptThreadGroup.java class InterruptThreadGroup {public static void main (String [] args) {MyThread mt = new MyThread (); mt.setName ("A"); mt.start (); mt = nový MyThread (); mt.setName ("B"); mt.start (); skus {Thread.sleep (2000); // Počkajte 2 sekundy} catch (InterruptedException e) {} // Prerušte všetky metódy v rovnakej skupine vlákien ako hlavné // vlákno Thread.currentThread () .getThreadGroup () .interrupt (); }} class MyThread extends Thread {public void run () {synchronized ("A") {System.out.println (getName () + "about to wait."); skúste {"A" .wait (); } catch (InterruptedException e) {System.out.println (getName () + "prerušené."); } System.out.println (getName () + "ukončenie."); }}}
$config[zx-auto] not found$config[zx-overlay] not found