Tämän kuukauden Java 101 päättää ketjusarjan keskittymällä ketjuryhmiin, volatiliteettiin, langan paikallisiin muuttujiin, ajastimiin ja KierreKuolema
luokassa.
Ymmärtäminen Java-ketjuista - lue koko sarja
- Osa 1: Esittely kierteet ja ajettavat
- Osa 2: Langan synkronointi
- Osa 3: Langan ajoitus, odotus / ilmoitus ja langan keskeytys
- Osa 4: Lankaryhmät, volatiliteetti, säie-paikalliset muuttujat, ajastimet ja langan kuolema
Lankaryhmät
Verkkopalvelinohjelmassa yksi ketju odottaa ja hyväksyy asiakasohjelmien pyynnöt esimerkiksi tietokantatapahtumien tai monimutkaisten laskelmien suorittamiseksi. Lanka luo yleensä uuden ketjun pyynnön käsittelemiseksi. Pyynnön määrästä riippuen useita eri ketjuja voi olla samanaikaisesti läsnä, mikä vaikeuttaa ketjujen hallintaa. Lankojen hallinnan yksinkertaistamiseksi ohjelmat järjestävät ketjut ketjuryhmät—java.lang.ThreadGroup
objektit, jotka ryhmittelevät aiheeseen liittyviä ketjuja ' Lanka
(ja Lanka
alaluokka) esineitä. Esimerkiksi ohjelmasi voi käyttää ThreadGroup
ryhmitellä kaikki tulostuslangat yhteen ryhmään.
merkintä: Jotta keskustelu olisi yksinkertaista, viittaan ketjuryhmiin ikään kuin ne järjestäisivät ketjuja. Todellisuudessa ketjuryhmät järjestyvät Lanka
(ja Lanka
alaluokka) objektit, jotka liittyvät ketjuihin.
Java vaatii jokaisen säikeen ja jokaisen ketjuryhmän - tallenna juuriketjuryhmä, järjestelmään
—Liittyä johonkin toiseen ketjuryhmään. Tämä järjestely johtaa hierarkkiseen säikeiden ryhmärakenteeseen, jonka alla oleva kuva havainnollistaa sovelluskontekstissa.

Kuvion rakenteen yläosassa on järjestelmään
ketjuryhmä. JVM: n luoma järjestelmään
ryhmä järjestää JVM-säikeet, jotka käsittelevät objektin viimeistelyä ja muita järjestelmän tehtäviä, ja toimii sovelluksen hierarkkisen säie-ryhmärakenteen juuriketjuryhmänä. Vain alla järjestelmään
on JVM: n luoma tärkein
ketjuryhmä, joka on järjestelmään
: n alalangan ryhmä (alaryhmä, lyhyesti). tärkein
sisältää ainakin yhden säikeen - JVM: n luoman pääkierteen, joka suorittaa tavu-koodin ohjeet main ()
menetelmä.
Alapuolella tärkein
ryhmä asuu alaryhmä 1
ja alaryhmä 2
alaryhmät, sovelluksen luomat alaryhmät (jotka kuvion sovellus luo). Lisäksi, alaryhmä 1
ryhmittelee kolme sovelluksen luomaa säiettä: lanka 1
, lanka 2
ja lanka 3
. Verrattuna, alaryhmä 2
ryhmittelee yhden sovelluksen luoman säikeen: minun säie
.
Nyt kun tiedät perusasiat, aloitetaan ketjuryhmien luominen.
Luo ketjuryhmiä ja yhdistä ketjut näihin ryhmiin
ThreadGroup
luokan SDK-dokumentaatio paljastaa kaksi rakentajaa: ThreadGroup (merkkijono)
ja ThreadGroup (ThreadGroup-vanhempi, merkkijonon nimi)
. Molemmat rakentajat luovat ketjuryhmän ja antavat sille nimen nimi
parametri määrittää. Rakentajat eroavat toisistaan valitsemalla, mikä säieryhmä toimii äskettäin uuden luodun säieryhmän vanhempana. Jokainen ketjuryhmä paitsi järjestelmään
, on oltava ylälangan ryhmä. Sillä ThreadGroup (merkkijono)
, ylätaso on sen ketjun ketjuryhmä, joka kutsuu ThreadGroup (merkkijono)
. Esimerkiksi, jos päälanka kutsuu ThreadGroup (merkkijono)
, uudella luodulla ketjuryhmällä on päälangan ryhmä vanhempana -tärkein
. Sillä ThreadGroup (ThreadGroup-vanhempi, merkkijonon nimi)
, vanhempi on ryhmä, joka vanhempi
viitteet. Seuraava koodi osoittaa, kuinka näitä rakentajia voidaan käyttää luomaan pari ketjuryhmää:
public staattinen void main (String [] argumentit) {ThreadGroup tg1 = uusi ThreadGroup ("A"); ThreadGroup tg2 = uusi ThreadGroup (tg1, "B"); }
Yllä olevassa koodissa päälanka luo kaksi ketjuryhmää: A
ja B
. Ensinnäkin päälanka luo A
soittamalla ThreadGroup (merkkijono)
. tg1
-viitattu ketjuryhmän vanhempi on tärkein
koska tärkein
on päälangan säieryhmä. Toiseksi päälanka luo B
soittamalla ThreadGroup (ThreadGroup-vanhempi, merkkijonon nimi)
. tg2
-viitattu ketjuryhmän vanhempi on A
koska tg1
viittaus välitetään argumenttina ThreadGroup (tg1, "B")
ja A
liittyy tg1
.
Kärki: Kun et enää tarvitse hierarkiaa ThreadGroup
esineitä, soita ThreadGroup
on mitätön tuhota ()
menetelmä viittaamalla ThreadGroup
hierarkian yläosassa oleva objekti. Jos alkuun ThreadGroup
esineestä ja kaikista alaryhmäobjekteista puuttuu säieobjekteja, tuhota()
valmistelee nämä säieryhmäobjektit roskien keräystä varten. Muuten, tuhota()
heittää an IllegalThreadStateException
esine. Siihen saakka, kunnes mitätöit viitteen alkuun ThreadGroup
objektin (olettaen, että kenttämuuttuja sisältää kyseisen viittauksen), roskien keräilijä ei voi kerätä kyseistä objektia. Viitaten ylimpään objektiin, voit selvittää, soitettiinko edellinen puhelu tuhota()
menetelmä soittamalla ThreadGroup
on totuusarvo on tuhottu ()
menetelmä. Tämä menetelmä palauttaa arvon tosi, jos ketjuryhmähierarkia tuhoutui.
Itse ketjuryhmät ovat hyödyttömiä. Voidakseen käyttää niitä heidän on ryhmitettävä ketjut. Ryhmittelet ketjut ketjuryhmiin ohittamalla ThreadGroup
viittaukset sopiviin Lanka
rakentajat:
ThreadGroup tg = uusi ThreadGroup ("alaryhmä 2"); Lanka t = uusi lanka (tg, "oma säie");
Yllä oleva koodi luo ensin a alaryhmä 2
ryhmän kanssa tärkein
vanhempana. (Oletan, että pääsäike suorittaa koodin.) Koodi luo seuraavaksi a minun säie
Lanka
esine alaryhmä 2
ryhmä.
Luodaan nyt sovellus, joka tuottaa hahmomme hierarkkisen säikeiden ryhmärakenteen:
Listaus 1. ThreadGroupDemo.java
// ThreadGroupDemo.java-luokka ThreadGroupDemo {public static void main (String [] argumentit) {ThreadGroup tg = uusi ThreadGroup ("alaryhmä 1"); Lanka t1 = uusi lanka (tg, "lanka 1"); Lanka t2 = uusi lanka (tg, "lanka 2"); Lanka t3 = uusi lanka (tg, "lanka 3"); tg = uusi ThreadGroup ("alaryhmä 2"); Kierre t4 = uusi ketju (tg, "oma säie"); tg = Thread.currentThread () .getThreadGroup (); int agc = tg.activeGroupCount (); System.out.println ("Aktiiviset ketjuryhmät ryhmässä" + tg.getName () + "ketjuryhmä:" + agc); tg.list (); }}
ThreadGroupDemo
luo sopivan ketjuryhmän ja säieobjektit vastaamaan yllä olevassa kuvassa näkyvää. Todistaa, että alaryhmä 1
ja alaryhmä 2
ryhmät ovat tärkein
ainoat alaryhmät, ThreadGroupDemo
tekee seuraavaa:
- Hakee viitteen pääketjuun
ThreadGroup
vastustaa soittamallaLanka
staattinencurrentThread ()
method (joka palauttaa viitteen pääketjuunLanka
esine), jota seuraaLanka
onThreadGroup getThreadGroup ()
menetelmä. - Puhelut
ThreadGroup
onint activeGroupCount ()
menetelmä juuri palautetussaThreadGroup
viite palauttaa estimaatti aktiivisten ryhmien päälangan säikeiden ryhmästä. - Puhelut
ThreadGroup
onMerkkijono getName ()
tapa palauttaa pääkierteen ketjuryhmän nimi. - Puhelut
ThreadGroup
ontyhjä luettelo ()
tapa tulostaa vakiolähtölaitteen tiedot päälangan säieryhmästä ja kaikista alaryhmistä.
Kun suoritetaan, ThreadGroupDemo
näyttää seuraavan lähdön:
Aktiiviset ketjuryhmät päälankeryhmässä: 2 java.lang.ThreadGroup [nimi = pää, maxpri = 10] Lanka [pää, 5, pää] Lanka [Lanka-0,5, pää] java.lang.ThreadGroup [nimi = alaryhmä 1, maxpri = 10] Lanka [lanka 1,5, alaryhmä 1] Lanka [lanka 2,5, alaryhmä 1] Lanka [lanka 3,5, alaryhmä 1] java.lang.ThreadGroup [nimi = alaryhmä 2, maxpri = 10 ] Lanka [minun ketju, 5, alaryhmä 2]
Lähtö, joka alkaa Lanka
tulokset lista()
sisäiset puhelut numeroon Lanka
on toString ()
menetelmää, osassa 1 kuvattua tulostusmuotoa. Tämän tuotoksen ohella näet tuloksen, joka alkaa java.lang.ThreadGroup
. Tämä lähtö identifioi ketjuryhmän nimen, jota seuraa sen suurin prioriteetti.
Prioriteetti- ja ketjuryhmät
Ketjuryhmän suurin prioriteetti on korkein prioriteetti, jonka sen ketjut voivat saavuttaa. Harkitse edellä mainittua verkkopalvelinohjelmaa. Kyseisessä ohjelmassa säie odottaa ja hyväksyy asiakasohjelmien pyynnöt. Ennen sen tekemistä wait-for / accept-request-säie voi ensin luoda ketjuryhmän, jonka suurin prioriteetti on juuri kyseisen ketjun prioriteetin alapuolella. Myöhemmin, kun pyyntö saapuu, wait-for / accept-request-ketju luo uuden ketjun vastaamaan asiakkaan pyyntöön ja lisää uuden ketjun aiemmin luotuun ketjuryhmään. Uuden säikeen prioriteetti laskee automaattisesti ketjuryhmän maksimiin. Tällä tavoin wait-for / accept-request-ketju vastaa pyyntöihin useammin, koska se toimii useammin.
Java antaa korkeimman prioriteetin kullekin ketjuryhmälle. Kun luot ryhmän, Java saa kyseisen prioriteetin vanhemmalta ryhmältä. Käyttää ThreadGroup
on void setMaxPriority (int prioriteetti)
menetelmä prioriteetin asettamiseksi myöhemmin. Säikeillä, jotka lisäät ryhmään sen jälkeen, kun olet asettanut sen enimmäisprioriteetin, prioriteetti ei saa ylittää maksimiarvoa. Kaikki korkeamman prioriteetin säikeet laskevat automaattisesti, kun ne liittyvät ketjuryhmään. Kuitenkin, jos käytät setMaxPriority (int prioriteetti)
Ryhmän enimmäisprioriteetin alentamiseksi kaikki ryhmään ennen tätä menetelmäkutsua lisätyt säikeet säilyttävät alkuperäiset prioriteettinsa. Esimerkiksi, jos lisäät prioriteetti 8 ketjun maksimiprioriteetti 9 -ryhmään ja sitten lasket ryhmän maksimiprioriteetin arvoon 7, prioriteetti 8 säie säilyy prioriteetilla 8. Voit milloin tahansa määrittää ketjuryhmän enimmäisprioriteetin soittamalla ThreadGroup
on int getMaxPriority ()
menetelmä. Esittelin prioriteetti- ja ketjuryhmät MaxPriorityDemo
:
Listaus 2. MaxPriorityDemo.java
// MaxPriorityDemo.java class MaxPriorityDemo {public static void main (String [] args) {ThreadGroup tg = new ThreadGroup ("A"); System.out.println ("tg suurin prioriteetti =" + tg.getMaxPriority ()); Lanka t1 = uusi lanka (tg, "X"); System.out.println ("t1 prioriteetti =" + t1.getPriority ()); t1.setPriority (ketju.NORM_PRIORITY + 1); System.out.println ("t1 prioriteetti setPriority () =" + t1.getPriority () jälkeen); tg.setMaxPriority (ketju.NORM_PRIORITY - 1); System.out.println ("tg suurin prioriteetti setMaxPriority () =" + tg.getMaxPriority () jälkeen); System.out.println ("t1 prioriteetti setMaxPriority () =" + t1.getPriority () jälkeen); Lanka t2 = uusi lanka (tg, "Y"); System.out.println ("t2 prioriteetti =" + t2.getPriority ()); t2.setPriority (ketju.NORM_PRIORITY); System.out.println ("t2 prioriteetti setPriority () =" + t2.getPriority () jälkeen); }}
Kun suoritetaan, MaxPriorityDemo
tuottaa seuraavan tuotoksen:
tg maksimiprioriteetti = 10 t1 prioriteetti = 5 t1 prioriteetti setPriority jälkeen () = 6 tg maksimiprioriteetti setMaxPriority jälkeen () = 4 t1 prioriteetti setMaxPriority jälkeen () = 6 t2 prioriteetti = 4 t2 prioriteetti setPriority jälkeen () = 4
Lankaryhmä A
(mikä tg
viitetiedot) alkaa korkeimmalla prioriteetilla (10). Lanka X
, jonka Lanka
esine t1
viittaa, liittyy ryhmään ja saa viisi prioriteetiltaan. Muutamme langan prioriteetin 6: ksi, mikä onnistuu, koska 6 on alle 10. Sitten soitamme setMaxPriority (int prioriteetti)
vähentää ryhmän suurin prioriteetti arvoon 4. Vaikka säie X
edelleen prioriteetti 6, uusi Y
säie saa 4 prioriteettinsa. Lopuksi yritys lisätä langankiertoa Y
5: n prioriteetti epäonnistuu, koska 5 on suurempi kuin 4.
merkintä:setMaxPriority (int prioriteetti)
säätää automaattisesti ketjuryhmän alaryhmien maksimiprioriteetin.
Sen lisäksi, että käytät ketjuryhmiä säikeiden prioriteetin rajoittamiseksi, voit suorittaa muita tehtäviä kutsumalla erilaisia ThreadGroup
menetelmät, joita sovelletaan kunkin ryhmän ketjuun. Menetelmiä ovat void suspend ()
, void jatkaa ()
, mitätön pysäytys ()
ja mitätöi keskeytys ()
. Koska Sun Microsystems on vanhentanut kolme ensimmäistä menetelmää (ne ovat vaarallisia), tutkimme vain keskeyttää()
.
Keskeytä ketjuryhmä
ThreadGroup
on keskeyttää()
menetelmä sallii ketjun keskeyttää tietyn ketjuryhmän ketjut ja alaryhmät. Tämä tekniikka osoittautuu tarkoituksenmukaiseksi seuraavissa tilanteissa: Sovelluksen pääkehys luo useita ketjuja, joista kukin suorittaa työn yksikköä. Koska kaikkien ketjujen on täytettävä vastaavat työyksikönsä, ennen kuin kukaan lanka voi tutkia tuloksia, kukin lanka odottaa, kun työyksikkö on valmis. Pääkierre valvoo työtilaa. Kun kaikki muut ketjut ovat odottaneet, päälanka kutsuu keskeyttää()
keskeyttää muiden ketjujen odotukset. Sitten nämä ketjut voivat tutkia ja käsitellä tuloksia. Listaus 3 osoittaa ketjuryhmän keskeytymisen:
Listaus 3. InterruptThreadGroup.java
// InterruptThreadGroup.java class InterruptThreadGroup {public static void main (String [] args) {MyThread mt = new MyThread (); mt.setName ("A"); mt.start (); mt = uusi MyThread (); mt.setName ("B"); mt.start (); kokeile {Thread.sleep (2000); // Odota 2 sekuntia} catch (InterruptedException e) {} // Keskeytä kaikki menetelmät samassa säieryhmässä kuin // // thread Thread.currentThread () .getThreadGroup () .interrupt (); }} luokka MyThread laajentaa säiettä {public void run () {synchronized ("A") {System.out.println (getName () + "odottaa".); kokeile {"A". Odota (); } catch (InterruptedException e) {System.out.println (getName () + "keskeytetty"); } System.out.println (getName () + "päättyvä"); }}}