Programiranje

Java 101: Razumevanje niti Java, 4. del: Skupine niti, nestanovitnost in lokalne spremenljivke niti

Ta mesec je Java 101 zaključuje serijo niti s poudarkom na skupinah niti, nestanovitnosti, lokalnih spremenljivkah niti, časovnikih in ThreadDeath razred.

Razumevanje niti Java - preberite celotno serijo

  • 1. del: Predstavljanje niti in izvedljivih datotek
  • 2. del: Sinhronizacija niti
  • 3. del: Načrtovanje niti, čakanje / obveščanje in prekinitev niti
  • 4. del: Skupine niti, volatilnost, lokalne spremenljivke niti, časovniki in smrt niti

Skupine niti

V programu omrežnega strežnika ena nit čaka in sprejema zahteve odjemalskih programov za izvajanje, na primer transakcij zbirke podatkov ali zapletenih izračunov. Nit običajno ustvari novo nit za obdelavo zahteve. Glede na obseg zahteve je lahko hkrati prisotnih veliko različnih niti, kar otežuje upravljanje niti. Da bi poenostavili upravljanje niti, programi organizirajo svoje niti z skupine nitijava.lang.ThreadGroup predmeti, ki združujejo povezane niti ' Navoj (in Navoj podrazred). Program lahko na primer uporablja ThreadGroup združiti vse niti za tiskanje v eno skupino.

Opomba: Da bo razprava enostavna, se sklicujem na skupine niti, kot da bi organizirale niti. V resnici se skupine niti organizirajo Navoj (in Navoj podrazred) objekti, povezani z nitmi.

Java zahteva vsako nit in vsako skupino niti - shranite skupino korenskih niti, sistem—Da se pridružite neki drugi skupini niti. Ta ureditev vodi do hierarhične strukture skupine niti, ki jo spodnja slika prikazuje v kontekstu aplikacije.

Na vrhu slike je znak sistem skupina niti. Ustvaril JVM sistem group organizira niti JVM, ki se ukvarjajo z dokončanjem predmetov in drugimi sistemskimi nalogami, in služi kot skupina korenskih niti niti v hierarhični strukturi skupine niti aplikacije. Tik spodaj sistem je ustvaril JVM glavni skupina niti, kar je sistempodskupina (na kratko podskupina). glavni vsebuje vsaj eno nit - glavno nit, ki jo je ustvaril JVM in izvaja navodila bajt-kode v glavni () metoda.

Spodaj glavni skupina prebiva v podskupina 1 in podskupina 2 podskupine, podskupine, ki jih ustvari aplikacija (ki jih ustvari aplikacija slike). Poleg tega podskupina 1 združi tri niti, ustvarjene z aplikacijami: nit 1, nit 2, in nit 3. V nasprotju, podskupina 2 združi eno nit, ki jo ustvari aplikacija: moja nit.

Zdaj, ko poznate osnove, začnimo z ustvarjanjem skupin niti.

Ustvarite skupine niti in z njimi povežite niti

The ThreadGroup dokumentacija SDK razreda razkriva dva konstruktorja: ThreadGroup (ime niza) in ThreadGroup (nadrejeni ThreadGroup, ime niza). Oba konstruktorja ustvarita skupino niti in ji daste ime kot ime parameter določa. Konstruktorji se razlikujejo glede izbire, katera skupina niti bo nadrejena novo ustvarjeni skupini niti. Vsaka skupina niti, razen sistem, mora imeti nadrejeno skupino niti. Za ThreadGroup (ime niza), nadrejena je skupina niti niti, ki kliče ThreadGroup (ime niza). Kot primer, če pokliče glavna nit ThreadGroup (ime niza), je na novo ustvarjena skupina niti matična skupina glavne niti -glavni. Za ThreadGroup (nadrejeni ThreadGroup, ime niza), starš je skupina, ki starš reference. Naslednja koda prikazuje, kako s temi konstruktorji ustvariti par skupin niti:

javna statična void main (String [] args) {ThreadGroup tg1 = new ThreadGroup ("A"); ThreadGroup tg2 = nova ThreadGroup (tg1, "B"); }

V zgornji kodi glavna nit ustvari dve skupini niti: A in B. Najprej ustvari glavna nit A s klicem ThreadGroup (ime niza). The tg1-referencirana nadrejena skupina niti je glavni Ker glavni je skupina niti glavne niti. Drugič, glavna nit ustvarja B s klicem ThreadGroup (nadrejeni ThreadGroup, ime niza). The tg2-referencirana nadrejena skupina niti je A Ker tg1sklic gre kot argument za ThreadGroup (tg1, "B") in A sodelavci z tg1.

Namig: Ko ne potrebujete več hierarhije ThreadGroup predmeti, klic ThreadGroupje void uniči () s sklicevanjem na ThreadGroup objekt na vrhu te hierarhije. Če vrh ThreadGroup objekt in vsi predmeti podskupin nimajo niti, uničiti () pripravi tiste predmete skupine niti za zbiranje smeti. V nasprotnem primeru uničiti () vrže IllegalThreadStateException predmet. Dokler ne izničite sklica na vrh ThreadGroup predmeta (ob predpostavki, da spremenljivka polja vsebuje to referenco), zbiralnik smeti tega predmeta ne more zbrati. S sklicevanjem na zgornji predmet lahko ugotovite, ali je bil predhodni klic opravljen uničiti () metoda s klicem ThreadGroupje boolean isDestroyed () metoda. Ta metoda vrne true, če je bila uničena hierarhija skupine niti.

Skupine niti so same po sebi neuporabne. Da bi bili koristni, morajo združiti niti. Nitke razvrstite v skupine niti s prenašanjem ThreadGroup sklicevanja na ustrezne Navoj konstruktorji:

ThreadGroup tg = nova ThreadGroup ("podskupina 2"); Tema t = nova nit (tg, "moja nit");

Zgornja koda najprej ustvari a podskupina 2 skupina z glavni kot nadrejena skupina. (Predvidevam, da glavna nit izvede kodo.) Koda nato ustvari datoteko moja nitNavoj predmet v podskupina 2 skupino.

Zdaj pa ustvarimo aplikacijo, ki ustvari hierarhično strukturo skupine nitov naše figure:

Seznam 1. ThreadGroupDemo.java

// ThreadGroupDemo.java razred ThreadGroupDemo {public static void main (String [] args) {ThreadGroup tg = new ThreadGroup ("podskupina 1"); Nit t1 = nova nit (tg, "nit 1"); Nit t2 = nova nit (tg, "nit 2"); Nit t3 = nova nit (tg, "nit 3"); tg = nova ThreadGroup ("podskupina 2"); Tema t4 = nova nit (tg, "moja nit"); tg = Thread.currentThread () .getThreadGroup (); int agc = tg.activeGroupCount (); System.out.println ("Aktivne skupine niti v" + tg.getName () + "skupina niti:" + agc); tg.list (); }}

ThreadGroupDemo ustvari ustrezno skupino niti in predmete niti, da zrcalijo tisto, kar vidite na zgornji sliki. Da bi dokazali, da podskupina 1 in podskupina 2 skupine so glavnisamo podskupine, ThreadGroupDemo naredi naslednje:

  1. Pridobi sklic na glavno nit ThreadGroup predmet s klicem Navojje statičen currentThread () metoda (ki vrne sklic na glavno nit Navoj predmet), čemur sledi Navojje ThreadGroup getThreadGroup () metoda.
  2. Klici ThreadGroupje int activeGroupCount () metoda na pravkar vrnjenem ThreadGroup sklic za vrnitev ocene aktivnih skupin znotraj skupine niti glavne niti.
  3. Klici ThreadGroupje String getName () metoda za vrnitev imena skupine niti glavne niti.
  4. Klici ThreadGroupje ničen seznam () metoda za tiskanje na standardni izhodni napravi podrobnosti o skupini niti glavne niti in vseh podskupinah.

Ko tečete, ThreadGroupDemo prikaže naslednji izhod:

Aktivne skupine niti v glavni skupini niti: 2 java.lang.ThreadGroup [name = main, maxpri = 10] Thread [main, 5, main] Thread [Thread-0,5, main] java.lang.ThreadGroup [name = podskupina 1, maxpri = 10] Nit [nit 1,5, podskupina 1] Nit [nit 2,5, podskupina 1] Nit [nit 3,5, podskupina 1] java.lang.ThreadGroup [ime = podskupina 2, maxpri = 10 ] Tema [moja nit, 5, podskupina 2]

Rezultat, ki se začne z Navoj rezultati iz seznam ()interni klici osebe Navojje toString () metoda, izhodni format, ki sem ga opisal v 1. delu. Skupaj s tem izhodom vidite izhod, ki se začne z java.lang.ThreadGroup. Ta izhod identificira ime skupine niti, ki ji sledi največja prednost.

Prednostne skupine in skupine niti

Največja prednost skupine niti je največja prednost, ki jo lahko doseže katera koli nit. Upoštevajte omenjeni program omrežnega strežnika. Znotraj tega programa nit čaka in sprejema zahteve odjemalskih programov. Preden lahko nit čakanja / sprejema-zahteve najprej ustvari skupino niti z največjo prednostjo tik pod prednostjo te niti. Kasneje, ko prispe zahteva, nit čakanja / sprejema-zahteve ustvari novo nit, da se odzove na zahtevo odjemalca, in doda novo nit v prej ustvarjeno skupino niti. Prednost nove niti se samodejno zniža na maksimum skupine niti. Tako se nit čakanja / sprejema-zahteve pogosteje odziva na zahteve, ker se pogosteje izvaja.

Java dodeli največjo prednost vsaki skupini niti. Ko ustvarite skupino, Java to prednost pridobi od nadrejene skupine. Uporaba ThreadGroupje void setMaxPriority (int prioriteta) metoda za naknadno nastavitev največje prioritete. Vse niti, ki jih dodate skupini, potem ko ste nastavili njeno največjo prioriteto, ne morejo imeti prednosti, ki presega najvišjo. Vsaka nit z višjo prioriteto se samodejno zniža, ko se pridruži skupini niti. Če pa uporabljate setMaxPriority (int prioriteta) če želite znižati največjo prednost skupine, vse niti, dodane skupini pred klicem metode, ohranijo svoje prvotne prioritete. Če na primer dodate nit prioritete 8 v skupino z največjo prednostjo 9 in nato znižate največjo prednost te skupine na 7, ostane nit prioritete 8 na prednostni 8. Kadar koli lahko določite največjo prednost skupine niti s klicem ThreadGroupje int getMaxPriority () metoda. Za prikaz prednostnih skupin in skupin niti sem napisal MaxPriorityDemo:

Seznam 2. MaxPriorityDemo.java

// MaxPriorityDemo.java razred MaxPriorityDemo {public static void main (String [] args) {ThreadGroup tg = new ThreadGroup ("A"); System.out.println ("tg največja prednost =" + tg.getMaxPriority ()); Nit t1 = nova nit (tg, "X"); System.out.println ("t1 prioritet =" + t1.getPriority ()); t1.setPriority (Thread.NORM_PRIORITY + 1); System.out.println ("prednost t1 po setPriority () =" + t1.getPriority ()); tg.setMaxPriority (Thread.NORM_PRIORITY - 1); System.out.println ("tg največja prednost po setMaxPriority () =" + tg.getMaxPriority ()); System.out.println ("prioriteta t1 po setMaxPriority () =" + t1.getPriority ()); Nit t2 = nova nit (tg, "Y"); System.out.println ("t2 prioritet =" + t2.getPriority ()); t2.setPriority (Thread.NORM_PRIORITY); System.out.println ("prioriteta t2 po setPriority () =" + t2.getPriority ()); }}

Ko tečete, MaxPriorityDemo ustvari naslednje rezultate:

tg največja prednost = 10 prednost t1 = 5 prednost t1 po setPriority () = 6 tg največja prednost po setMaxPriority () = 4 t1 prednost po setMaxPriority () = 6 t2 prioriteta = 4 t2 prednost po setPriority () = 4

Skupina niti A (ki tg sklicev) se začne z največjo prioriteto (10). Navoj X, čigar Navoj predmet t1 sklicev, se pridruži skupini in prejme 5 kot prednostno nalogo. Prednost te niti spremenimo na 6, kar uspe, ker je 6 manj kot 10. Nato pokličemo setMaxPriority (int prioriteta) za zmanjšanje največje prioritete skupine na 4. Čeprav nit X ostaja prednostna naloga 6, novo dodana Y. nit prejme 4 kot prednostno nalogo. Končno, poskus povečanja niti Y.Prednost 5 ne uspe, ker je 5 večja od 4.

Opomba:setMaxPriority (int prioriteta) samodejno prilagodi največjo prednost podskupin skupine niti.

Poleg uporabe skupin niti za omejevanje prioritete niti lahko tudi druge naloge opravljate tako, da pokličete različne ThreadGroup metode, ki veljajo za nit vsake skupine. Metode vključujejo void suspend (), neveljavno nadaljevanje (), void stop (), in void interrupt (). Ker je družba Sun Microsystems opustila prve tri metode (niso varne), preučujemo samo prekinitev ().

Prekinite skupino niti

ThreadGroupje prekinitev () metoda omogoča, da nit prekine niti in podskupine določene skupine niti. Ta tehnika bi se izkazala za primerno v naslednjem scenariju: Glavna nit aplikacije ustvari več niti, ki vsaka opravijo enoto dela. Ker morajo vse niti dokončati ustrezne delovne enote, preden lahko katera koli nit preuči rezultate, vsaka nit po zaključku svoje delovne enote počaka. Glavna nit spremlja stanje dela. Ko vse druge niti čakajo, pokliče glavna nit prekinitev () da prekine čakanje drugih niti. Nato lahko te niti preučijo in obdelajo rezultate. Seznam 3 prikazuje prekinitev skupine niti:

Seznam 3. InterruptThreadGroup.java

// InterruptThreadGroup.java razred InterruptThreadGroup {public static void main (String [] args) {MyThread mt = new MyThread (); mt.setName ("A"); mt.start (); mt = novo MyThread (); mt.setName ("B"); mt.start (); poskusite {Thread.sleep (2000); // Počakajte 2 sekundi} catch (InterruptedException e) {} // Prekinite vse metode v isti skupini niti kot glavna // nit Thread.currentThread () .getThreadGroup () .interrupt (); }} razred MyThread razširja Thread {javni void run () {sinhronizirano ("A") {System.out.println (getName () + "kmalu čaka."); poskusite {"A" .wait (); } catch (InterruptedException e) {System.out.println (getName () + "interrupted."); } System.out.println (getName () + "konča."); }}}
$config[zx-auto] not found$config[zx-overlay] not found