Denne månedens Java 101 avslutter trådserien med å fokusere på trådgrupper, volatilitet, tråd-lokale variabler, tidtakere og TrådDød
klasse.
Forstå Java-tråder - les hele serien
- Del 1: Introduksjon av tråder og løpere
- Del 2: Trådesynkronisering
- Del 3: Trådplanlegging, vent / varsling og trådavbrudd
- Del 4: Trådgrupper, volatilitet, tråd-lokale variabler, tidtakere og tråddød
Trådgrupper
I et nettverksserverprogram venter en tråd på og godtar forespørsler fra klientprogrammer om å utføre, for eksempel databasetransaksjoner eller komplekse beregninger. Tråden oppretter vanligvis en ny tråd for å håndtere forespørselen. Avhengig av forespørselsvolumet, kan mange forskjellige tråder være til stede samtidig, noe som kompliserer trådadministrasjonen. For å forenkle trådadministrasjon, organiserer programmer trådene sine med trådgrupper—java.lang.ThreadGroup
objekter som grupperer relaterte tråder ' Tråd
(og Tråd
underklasse) objekter. For eksempel kan programmet ditt bruke Trådgruppe
for å gruppere alle utskriftstrådene i en gruppe.
Merk: For å holde diskusjonen enkel refererer jeg til trådgrupper som om de organiserer tråder. I virkeligheten organiserer trådgrupper Tråd
(og Tråd
underklasse) objekter tilknyttet tråder.
Java krever hver tråd og hver trådgruppe - lagre rottrådgruppen, system
—For å bli med i en annen trådgruppe. Denne ordningen fører til en hierarkisk trådgruppestruktur, som figuren nedenfor illustrerer i en applikasjonssammenheng.
På toppen av figurens struktur er system
trådgruppe. JVM-opprettet system
group organiserer JVM-tråder som håndterer objektavslutning og andre systemoppgaver, og fungerer som rottrådgruppe i applikasjonens hierarkiske trådgruppestruktur. Rett under system
er det JVM-laget hoved-
trådgruppe, som er system
sin undertrådegruppe (undergruppe, for kort). hoved-
inneholder minst én tråd - den JVM-opprettet hovedtråden som utfører byte-kodeinstruksjoner i hoved()
metode.
Under hoved-
gruppen bor i undergruppe 1
og undergruppe 2
undergrupper, applikasjonsopprettede undergrupper (som figurens applikasjon oppretter). Dessuten, undergruppe 1
grupperer tre applikasjonsopprettede tråder: tråd 1
, tråd 2
, og tråd 3
. I motsetning, undergruppe 2
grupperer en applikasjonsopprettet tråd: tråden min
.
Nå som du vet det grunnleggende, la oss begynne å lage trådgrupper.
Opprett trådgrupper og knytt tråder til disse gruppene
De Trådgruppe
klassens SDK-dokumentasjon avslører to konstruktører: ThreadGroup (strengnavn)
og ThreadGroup (overordnet ThreadGroup, strengnavn)
. Begge konstruktørene oppretter en trådgruppe og gir den et navn, som Navn
parameter spesifiserer. Konstruktørene skiller seg i valg av hvilken trådgruppe som fungerer som overordnet til den nyopprettede trådgruppen. Hver trådgruppe, unntatt system
, må ha en overordnet trådgruppe. Til ThreadGroup (strengnavn)
, er overordnet trådgruppen til tråden som ringer ThreadGroup (strengnavn)
. Som et eksempel, hvis hovedtråden ringer ThreadGroup (strengnavn)
, den nyopprettede trådgruppen har hovedtrådens gruppe som overordnet—hoved-
. Til ThreadGroup (overordnet ThreadGroup, strengnavn)
, foreldrene er gruppen som foreldre
referanser. Følgende kode viser hvordan du bruker disse konstruktørene til å lage et par trådgrupper:
public static void main (String [] args) {ThreadGroup tg1 = new ThreadGroup ("A"); ThreadGroup tg2 = ny ThreadGroup (tg1, "B"); }
I koden ovenfor oppretter hovedtråden to trådgrupper: EN
og B
. For det første skaper hovedtråden EN
ved å ringe ThreadGroup (strengnavn)
. De tg1
- referert trådgruppens foreldre er hoved-
fordi hoved-
er hovedtrådens trådgruppe. For det andre skaper hovedtråden B
ved å ringe ThreadGroup (overordnet ThreadGroup, navn på streng)
. De tg2
- referert trådgruppens foreldre er EN
fordi tg1
referanse går som et argument til Trådgruppe (tg1, "B")
og EN
forbinder med tg1
.
Tips: Når du ikke lenger trenger et hierarki av Trådgruppe
gjenstander, ring Trådgruppe
s ugyldig ødelegge ()
metoden via en referanse til Trådgruppe
objekt på toppen av det hierarkiet. Hvis toppen Trådgruppe
objekt og alle undergruppeobjekter mangler trådobjekter, ødelegge()
forbereder trådgruppegjenstandene for søppeloppsamling. Ellers, ødelegge()
kaster en IllegalThreadStateException
gjenstand. Imidlertid til du opphever referansen til toppen Trådgruppe
objekt (forutsatt at en feltvariabel inneholder den referansen), kan ikke søppeloppsamleren samle inn det objektet. Med henvisning til det øverste objektet kan du avgjøre om en tidligere samtale ble ringt til ødelegge()
metode ved å ringe Trådgruppe
s boolsk er ødelagt ()
metode. Denne metoden blir sant hvis trådgruppehierarkiet ble ødelagt.
I seg selv er trådgrupper ubrukelige. For å være til nytte må de gruppere tråder. Du grupperer tråder i trådgrupper ved å passere Trådgruppe
referanser til passende Tråd
konstruksjoner:
ThreadGroup tg = new ThreadGroup ("undergruppe 2"); Tråd t = ny tråd (tg, "tråden min");
Koden ovenfor oppretter først en undergruppe 2
gruppe med hoved-
som foreldregruppe. (Jeg antar at hovedtråden utfører koden.) Koden oppretter deretter en tråden min
Tråd
objekt i undergruppe 2
gruppe.
La oss nå lage et program som produserer figurens hierarkiske trådgruppestruktur:
Oppføring 1. ThreadGroupDemo.java
// ThreadGroupDemo.java klasse ThreadGroupDemo {public static void main (String [] args) {ThreadGroup tg = new ThreadGroup ("subgroup 1"); Tråd t1 = ny tråd (tg, "tråd 1"); Tråd t2 = ny tråd (tg, "tråd 2"); Tråd t3 = ny tråd (tg, "tråd 3"); tg = ny trådgruppe ("undergruppe 2"); Tråd t4 = ny tråd (tg, "tråden min"); tg = Thread.currentThread () .getThreadGroup (); int agc = tg.activeGroupCount (); System.out.println ("Aktive trådgrupper i" + tg.getName () + "trådgruppe:" + agc); tg.list (); }}
ThreadGroupDemo
oppretter riktig trådgruppe og trådobjekter for å speile det du ser i figuren ovenfor. For å bevise at undergruppe 1
og undergruppe 2
grupper er hoved-
bare undergrupper, ThreadGroupDemo
gjør følgende:
- Henter en referanse til hovedtråden
Trådgruppe
objekt ved å ringeTråd
er statiskgjeldende tråd ()
metode (som returnerer en referanse til hovedtrådenTråd
objekt) etterfulgt avTråd
sThreadGroup getThreadGroup ()
metode. - Ringer
Trådgruppe
sint activeGroupCount ()
metoden på nettopp returnerteTrådgruppe
referanse for å returnere et estimat av aktive grupper innenfor hovedtrådens trådgruppe. - Ringer
Trådgruppe
sString getName ()
metode for å returnere hovedtrådens trådgruppenavn. - Ringer
Trådgruppe
sugyldig liste ()
metode for å skrive ut på standard utdataenhetsdetaljer på hovedtrådens trådgruppe og alle undergrupper.
Når du løper, ThreadGroupDemo
viser følgende utgang:
Aktive trådgrupper i hovedtrådgruppe: 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] Tråd [tråd 1,5, undergruppe 1] Tråd [tråd 2,5, undergruppe 1] Tråd [tråd 3,5, undergruppe 1] java.lang.ThreadGroup [navn = undergruppe 2, maxpri = 10 ] Tråd [tråden min, 5, undergruppe 2]
Utgang som begynner med Tråd
resultater fra liste()
sine interne samtaler til Tråd
s toString ()
metode, et utdataformat jeg beskrev i del 1. Sammen med den utgangen ser du utdata som begynner med java.lang.ThreadGroup
. Denne utgangen identifiserer trådgruppens navn etterfulgt av maksimal prioritet.
Prioritets- og trådgrupper
En trådgruppes maksimale prioritet er den høyeste prioriteten noen av trådene kan oppnå. Tenk på det nevnte nettverksserverprogrammet. Innenfor programmet venter en tråd på og godtar forespørsler fra klientprogrammer. Før du gjør det, kan ventetiden / godta-forespørselstråden først opprette en trådgruppe med maksimal prioritet rett under trådens prioritet. Senere, når en forespørsel kommer, oppretter ventetiden / godtar forespørselstråden en ny tråd for å svare på klientforespørselen og legger til den nye tråden i den tidligere opprettede trådgruppen. Den nye trådens prioritet senkes automatisk til trådgruppens maksimum. På den måten svarer ventetiden / godta-forespørselstråden oftere på forespørsler fordi den kjører oftere.
Java tildeler maksimal prioritet til hver trådgruppe. Når du oppretter en gruppe, får Java den prioriteten fra foreldregruppen. Bruk Trådgruppe
s ugyldig setMaxPriority (int prioritet)
metode for å deretter sette maksimal prioritet. Alle tråder du legger til i gruppen etter at du har angitt maksimal prioritet, kan ikke ha en prioritet som overstiger maksimumet. Enhver tråd med høyere prioritet senkes automatisk når den blir med i trådgruppen. Imidlertid, hvis du bruker setMaxPriority (int prioritet)
for å senke en gruppes maksimale prioritet, beholder alle trådene som legges til gruppen før metoden, de opprinnelige prioriteringene. Hvis du for eksempel legger til en prioritet 8-tråd til en gruppe med maksimal prioritet 9, og deretter senker gruppens maksimale prioritet til 7, forblir prioritet 8-tråden i prioritet 8. Du kan når som helst bestemme en trådgruppes maksimale prioritet Trådgruppe
s int getMaxPriority ()
metode. For å demonstrere prioritets- og trådgrupper, skrev jeg MaxPriorityDemo
:
Oppføring 2. MaxPriorityDemo.java
// MaxPriorityDemo.java klasse MaxPriorityDemo {public static void main (String [] args) {ThreadGroup tg = new ThreadGroup ("A"); System.out.println ("tg maksimal prioritet =" + tg.getMaxPriority ()); Tråd t1 = ny tråd (tg, "X"); System.out.println ("t1 prioritet =" + t1.getPriority ()); t1.setPriority (Thread.NORM_PRIORITY + 1); System.out.println ("t1 prioritet etter setPriority () =" + t1.getPriority ()); tg.setMaxPriority (tråd.NORM_PRIORITY - 1); System.out.println ("tg maksimal prioritet etter setMaxPriority () =" + tg.getMaxPriority ()); System.out.println ("t1 prioritet etter setMaxPriority () =" + t1.getPriority ()); Tråd t2 = ny tråd (tg, "Y"); System.out.println ("t2 prioritet =" + t2.getPriority ()); t2.setPriority (tråd.NORM_PRIORITY); System.out.println ("t2 prioritet etter setPriority () =" + t2.getPriority ()); }}
Når du løper, MaxPriorityDemo
produserer følgende utgang:
tg maksimal prioritet = 10 t1 prioritet = 5 t1 prioritet etter sett Prioritet () = 6 tg maksimal prioritet etter settMaksPrioritet () = 4 t1 prioritet etter sett
Trådgruppe EN
(hvilken tg
referanser) starter med høyeste prioritet (10) som maksimum. Tråd X
, hvem sin Tråd
gjenstand t1
referanser, blir med i gruppen og får 5 som prioritet. Vi endrer trådens prioritet til 6, som lykkes fordi 6 er mindre enn 10. Deretter kaller vi setMaxPriority (int prioritet)
for å redusere gruppens maksimale prioritet til 4. Selv om tråden X
forblir på prioritet 6, en nylig lagt til Y
tråden mottar 4 som sin prioritet. Endelig et forsøk på å øke tråden Y
prioritet til 5 mislykkes, fordi 5 er større enn 4.
Merk:setMaxPriority (int prioritet)
justerer automatisk maksimal prioritet for en trådgruppes undergrupper.
I tillegg til å bruke trådgrupper for å begrense trådprioritet, kan du utføre andre oppgaver ved å ringe forskjellige Trådgruppe
metoder som gjelder for hver gruppes tråd. Metoder inkluderer ugyldig suspendere ()
, ugyldig CV ()
, ugyldig stopp ()
, og ugyldig avbrudd ()
. Fordi Sun Microsystems har avviklet de tre første metodene (de er usikre), undersøker vi bare avbryte()
.
Avbryt en trådgruppe
Trådgruppe
s avbryte()
metoden lar en tråd avbryte trådene og undergruppene til en bestemt trådgruppe. Denne teknikken vil vise seg å være hensiktsmessig i følgende scenario: Programmets hovedtråd oppretter flere tråder som hver utfører en arbeidsenhet. Fordi alle tråder må fullføre sine respektive arbeidsenheter før en tråd kan undersøke resultatene, venter hver tråd etter å ha fullført arbeidsenheten. Hovedtråden overvåker arbeidstilstanden. Når alle andre tråder venter, ringer hovedtråden avbryte()
å avbryte ventetiden til de andre trådene. Så kan disse trådene undersøke og behandle resultatene. Oppføring 3 demonstrerer avbrudd i trådgruppen:
Oppføring 3. InterruptThreadGroup.java
// InterruptThreadGroup.java klasse InterruptThreadGroup {public static void main (String [] args) {MyThread mt = new MyThread (); mt.setName ("A"); mt.start (); mt = ny MyThread (); mt.setName ("B"); mt.start (); prøv {Thread.sleep (2000); // Vent 2 sekunder} fangst (InterruptedException e) {} // Avbryt alle metodene i samme trådgruppe som hoved // thread Thread.currentThread () .getThreadGroup () .interrupt (); }} klasse MyThread utvider tråd {public void run () {synkronisert ("A") {System.out.println (getName () + "i ferd med å vente."); prøv {"A" .wait (); } fange (InterruptedException e) {System.out.println (getName () + "avbrutt."); } System.out.println (getName () + "avslutter."); }}}