Ohjelmointi

Java 101: Ymmärtäminen Java-ketjuista, osa 4: Kierreryhmät, volatiliteetti ja säikeiden paikalliset muuttujat

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ätjava.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 2ja 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 tg1viittaus välitetään argumenttina ThreadGroup (tg1, "B") ja A liittyy tg1.

Kärki: Kun et enää tarvitse hierarkiaa ThreadGroup esineitä, soita ThreadGroupon 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 ThreadGroupon 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äieLanka 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ärkeinainoat alaryhmät, ThreadGroupDemo tekee seuraavaa:

  1. Hakee viitteen pääketjuun ThreadGroup vastustaa soittamalla Lankastaattinen currentThread () method (joka palauttaa viitteen pääketjuun Lanka esine), jota seuraa Lankaon ThreadGroup getThreadGroup () menetelmä.
  2. Puhelut ThreadGroupon int activeGroupCount () menetelmä juuri palautetussa ThreadGroup viite palauttaa estimaatti aktiivisten ryhmien päälangan säikeiden ryhmästä.
  3. Puhelut ThreadGroupon Merkkijono getName () tapa palauttaa pääkierteen ketjuryhmän nimi.
  4. Puhelut ThreadGroupon tyhjä 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 Lankaon 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ää ThreadGroupon 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 ThreadGroupon 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 Y5: 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ä

ThreadGroupon 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ä"); }}}
$config[zx-auto] not found$config[zx-overlay] not found