Šī mēneša Java 101 noslēdz pavedienu sēriju, koncentrējoties uz pavedienu grupām, svārstīgumu, pavedienu lokālajiem mainīgajiem, taimeriem un ThreadDeath
klasē.
Izpratne par Java pavedieniem - izlasiet visu sēriju
- 1. daļa: Vītņu un skrējienu iepazīstināšana
- 2. daļa: Vītnes sinhronizācija
- 3. daļa: Vītņu plānošana, gaidīšana / paziņošana un pavedienu pārtraukšana
- 4. daļa: pavedienu grupas, svārstīgums, lokālie pavedienu mainīgie, taimeri un pavedienu bojāeja
Vītņu grupas
Tīkla servera programmā viena pavediens gaida un pieņem klienta programmu pieprasījumus izpildīt, piemēram, datu bāzes darījumus vai sarežģītus aprēķinus. Vītne parasti izveido jaunu pavedienu, lai apstrādātu pieprasījumu. Atkarībā no pieprasījuma apjoma vienlaikus var būt daudz dažādu pavedienu, kas sarežģī pavedienu pārvaldību. Lai vienkāršotu pavedienu pārvaldību, programmas sakārto savus pavedienus pavedienu grupas—java.lang.ThreadGroup
objekti, kas grupē saistītos pavedienus ' Vītne
(un Vītne
apakšklase) objekti. Piemēram, jūsu programma var izmantot ThreadGroup
lai visus drukas pavedienus sagrupētu vienā grupā.
Piezīme: Lai diskusija būtu vienkārša, es atsaucos uz pavedienu grupām, it kā tās sakārtotu pavedienus. Patiesībā pavedienu grupas organizējas Vītne
(un Vītne
apakšklase) objekti, kas saistīti ar pavedieniem.
Java prasa katru pavedienu un katru pavedienu grupu - saglabājiet saknes pavedienu grupu, sistēmā
- pievienoties kādai citai pavedienu grupai. Šī vienošanās noved pie hierarhiskas pavedienu grupas struktūras, kuru zemāk redzamais attēls ilustrē lietojuma kontekstā.
Attēla struktūras augšpusē ir sistēmā
pavedienu grupa. JVM izveidots sistēmā
grupa organizē JVM pavedienus, kas nodarbojas ar objektu pabeigšanu un citiem sistēmas uzdevumiem, un kalpo kā lietojumprogrammas hierarhiskās pavedienu grupas struktūras saknes pavedienu grupa. Tikai zemāk sistēmā
ir JVM izveidots galvenais
pavedienu grupa, kas ir sistēmā
apakšvītņu grupa (īsāk - apakšgrupa). galvenais
satur vismaz vienu pavedienu - JVM izveidoto galveno pavedienu, kas izpilda baita koda instrukcijas galvenais ()
metodi.
Zem galvenais
grupa dzīvo 1. apakšgrupa
un 2. apakšgrupa
apakšgrupas, lietojumprogrammas izveidotas apakšgrupas (kuras attēla lietojumprogramma izveido). Turklāt 1. apakšgrupa
sagrupē trīs lietojumprogrammas izveidotus pavedienus: 1. pavediens
, 2. pavediens
, un 3. pavediens
. Turpretī 2. apakšgrupa
sagrupē vienu lietojumprogrammas izveidotu pavedienu: mans pavediens
.
Tagad, kad jūs zināt pamatus, sāksim veidot pavedienu grupas.
Izveidojiet pavedienu grupas un saistiet pavedienus ar šīm grupām
The ThreadGroup
klases SDK dokumentācija atklāj divus konstruktorus: ThreadGroup (virknes nosaukums)
un ThreadGroup (ThreadGroup vecāks, virknes nosaukums)
. Abi konstruktori izveido pavedienu grupu un piešķir tai nosaukumu nosaukums
parametrs norāda. Konstruktori atšķiras pēc izvēles, kāda pavedienu grupa kalpo kā vecākā jaunizveidotajai pavedienu grupai. Katra pavedienu grupa, izņemot sistēmā
, jābūt vecāku pavedienu grupai. Priekš ThreadGroup (virknes nosaukums)
, vecāks ir pavediena pavedienu grupa, kas izsauc ThreadGroup (virknes nosaukums)
. Piemēram, ja zvana galvenais pavediens ThreadGroup (virknes nosaukums)
, jaunizveidotajai pavedienu grupai ir galvenā pavediena grupa -galvenais
. Priekš ThreadGroup (ThreadGroup vecāks, virknes nosaukums)
, vecāks ir tā grupa vecāks
atsauces. Šis kods parāda, kā izmantot šos konstruktorus, lai izveidotu pavedienu grupu pāri:
public static void main (String [] args) {ThreadGroup tg1 = jauna ThreadGroup ("A"); ThreadGroup tg2 = jauna ThreadGroup (tg1, "B"); }
Iepriekš minētajā kodā galvenais pavediens izveido divas pavedienu grupas: A
un B
. Pirmkārt, galvenais pavediens rada A
piezvanot ThreadGroup (virknes nosaukums)
. The tg1
-referencē pavedienu grupas vecāks ir galvenais
jo galvenais
ir galvenā pavediena pavedienu grupa. Otrkārt, galvenais pavediens rada B
piezvanot ThreadGroup (ThreadGroup vecāks, virknes nosaukums)
. The tg2
-referencē pavedienu grupas vecāks ir A
jo tg1
atsauce pāriet kā arguments uz ThreadGroup (tg1, "B")
un A
asociējas ar tg1
.
Padoms: Pēc tam, kad jums vairs nav nepieciešama hierarhija ThreadGroup
objekti, zvaniet ThreadGroup
's anulēt iznīcināt ()
metode, izmantojot atsauci uz ThreadGroup
objekts šīs hierarhijas augšdaļā. Ja augšā ThreadGroup
objektam un visiem apakšgrupas objektiem trūkst pavedienu objektu, iznīcināt()
sagatavo tos pavedienu grupas objektus atkritumu savākšanai. Pretējā gadījumā iznīcināt()
met an IllegalThreadStateException
objekts. Tomēr, kamēr jūs neatceļat atsauci uz augšu ThreadGroup
objektu (pieņemot, ka lauka mainīgajā ir šī atsauce), atkritumu savācējs nevar savākt šo objektu. Atsaucoties uz augšējo objektu, jūs varat noteikt, vai iepriekš tika zvanīts uz iznīcināt()
metodi, zvanot ThreadGroup
's Boolean isDestroyed ()
metodi. Šī metode atgriežas kā taisnība, ja pavedienu grupas hierarhija tika iznīcināta.
Pats par sevi pavedienu grupas ir bezjēdzīgas. Lai tos varētu izmantot, viņiem ir jāgrupē pavedieni. Jūs grupējat pavedienus pavedienu grupās, pārejot ThreadGroup
atsauces uz piemērotu Vītne
konstruktori:
ThreadGroup tg = jauna ThreadGroup ("2. apakšgrupa"); Thread t = new Thread (tg, "mans pavediens");
Iepriekš minētais kods vispirms izveido a 2. apakšgrupa
grupa ar galvenais
kā vecāku grupa. (Es pieņemu, ka galvenais pavediens izpilda kodu.) Nākamais kods izveido a mans pavediens
Vītne
objekts 2. apakšgrupa
grupa.
Tagad izveidosim lietojumprogrammu, kas izveido mūsu figūras hierarhisko pavedienu grupas struktūru:
Saraksts 1. ThreadGroupDemo.java
// ThreadGroupDemo.java klase ThreadGroupDemo {public static void main (String [] args) {ThreadGroup tg = jauna ThreadGroup ("1. apakšgrupa"); Pavediens t1 = jauns pavediens (tg, "pavediens 1"); Pavediens t2 = jauns pavediens (tg, "pavediens 2"); Pavediens t3 = jauns pavediens (tg, "pavediens 3"); tg = jauna ThreadGroup ("2. apakšgrupa"); Pavediens t4 = jauns pavediens (tg, "mans pavediens"); tg = Thread.currentThread () .getThreadGroup (); int agc = tg.activeGroupCount (); System.out.println ("Aktīvās pavedienu grupas" + tg.getName () + "pavedienu grupā:" + agc); tg.list (); }}
ThreadGroupDemo
izveido atbilstošu pavedienu grupu un pavedienu objektus, lai atspoguļotu to, ko redzat attēlā. Lai pierādītu, ka 1. apakšgrupa
un 2. apakšgrupa
grupas ir galvenais
ir tikai apakšgrupas, ThreadGroupDemo
veic šādas darbības:
- Izgūst atsauci uz galvenajiem pavedieniem
ThreadGroup
iebilst, piezvanotVītne
ir statiskacurrentThread ()
metode (kas atgriež atsauci uz galvenajiem pavedieniemVītne
objekts), kam sekoVītne
'sThreadGroup getThreadGroup ()
metodi. - Zvani
ThreadGroup
'sint activeGroupCount ()
metode tikko atgrieztajāThreadGroup
atsauce, lai atgrieztu aktīvo grupu tāmi galvenā pavediena pavedienu grupā. - Zvani
ThreadGroup
'sVirkne getName ()
metode, lai atgrieztu galvenā pavediena pavedienu grupas nosaukumu. - Zvani
ThreadGroup
'snederīgs saraksts ()
metode, kā drukāt uz standarta izvades ierīces informāciju par galvenā pavediena pavedienu grupu un visām apakšgrupām.
Palaist, ThreadGroupDemo
parāda šādu izvadi:
Aktīvās pavedienu grupas galvenajā pavedienu grupā: 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] Vītne [pavediens 1,5, 1. apakšgrupa] Vītne [pavediens 2,5, 1. apakšgrupa] Vītne [pavediens 3,5, 1. apakšgrupa] java.lang.ThreadGroup [nosaukums = 2. apakšgrupa, maxpri = 10 ] Vītne [mans pavediens, 5., 2. apakšgrupa]
Rezultāts, kas sākas ar Vītne
rezultāti no saraksts ()
iekšējie zvani uz Vītne
's toString ()
metodi, izejas formātu, kuru es aprakstīju 1. daļā. Kopā ar šo izvadi jūs redzat izvades sākumu ar java.lang.ThreadGroup
. Šī izeja identificē pavedienu grupas nosaukumu, kam seko tā maksimālā prioritāte.
Prioritātes un pavedienu grupas
Pavedienu grupas maksimālā prioritāte ir augstākā prioritāte, kādu var sasniegt visi tās pavedieni. Apsveriet iepriekš minēto tīkla servera programmu. Šīs programmas ietvaros pavediens gaida un pieņem klienta programmu pieprasījumus. Pirms to izdarīt, gaidīšanas / pieņemšanas pieprasījuma pavediens vispirms var izveidot pavedienu grupu ar maksimālo prioritāti tieši zem šīs pavediena prioritātes. Vēlāk, kad pienāk pieprasījums, gaidīšanas / pieņemšanas-pieprasījuma pavediens izveido jaunu pavedienu, lai atbildētu uz klienta pieprasījumu, un pievieno jaunu pavedienu iepriekš izveidotajai pavedienu grupai. Jaunā pavediena prioritāte automātiski samazinās līdz maksimālajai pavedienu grupai. Tādā veidā gaidīšanas / pieņemšanas-pieprasījuma pavediens biežāk reaģē uz pieprasījumiem, jo tas darbojas biežāk.
Java katrai pavedienu grupai piešķir maksimālo prioritāti. Kad izveidojat grupu, Java iegūst šo prioritāti no vecāku grupas. Izmantot ThreadGroup
's void setMaxPriority (int prioritāte)
metodi pēc tam noteikt maksimālo prioritāti. Visiem pavedieniem, kurus pievienojat grupai pēc maksimālās prioritātes iestatīšanas, prioritāte nedrīkst pārsniegt maksimālo. Jebkurš pavediens ar augstāku prioritāti automātiski pazeminās, pievienojoties pavedienu grupai. Tomēr, ja jūs izmantojat setMaxPriority (int prioritāte)
lai pazeminātu grupas maksimālo prioritāti, visi grupai pirms šīs metodes izsaukuma pievienotie pavedieni saglabā to sākotnējās prioritātes. Piemēram, ja jūs pievienojat 8. prioritātes pavedienu maksimālās 9. grupas grupai un pēc tam pazemina šīs grupas maksimālo prioritāti līdz 7, 8. prioritātes pavediens paliek prioritārā 8. Jebkurā laikā varat noteikt pavedienu grupas maksimālo prioritāti, zvanot ThreadGroup
's int getMaxPriority ()
metodi. Lai parādītu prioritāšu un pavedienu grupas, es uzrakstīju MaxPriorityDemo
:
Saraksts 2. MaxPriorityDemo.java
// MaxPriorityDemo.java klase MaxPriorityDemo {public static void main (String [] args) {ThreadGroup tg = new ThreadGroup ("A"); System.out.println ("tg maksimālā prioritāte =" + tg.getMaxPriority ()); Pavediens t1 = jauns pavediens (tg, "X"); System.out.println ("t1 prioritāte =" + t1.getPriority ()); t1.setPriority (Thread.NORM_PRIORITY + 1); System.out.println ("t1 prioritāte pēc setPriority () =" + t1.getPriority ()); tg.setMaxPriority (Thread.NORM_PRIORITY - 1); System.out.println ("tg maksimālā prioritāte pēc setMaxPriority () =" + tg.getMaxPriority ()); System.out.println ("t1 prioritāte pēc setMaxPriority () =" + t1.getPriority ()); Pavediens t2 = jauns pavediens (tg, "Y"); System.out.println ("t2 prioritāte =" + t2.getPriority ()); t2.setPriority (Thread.NORM_PRIORITY); System.out.println ("t2 prioritāte pēc setPriority () =" + t2.getPriority ()); }}
Palaist, MaxPriorityDemo
rada šādu izvadi:
tg maksimālā prioritāte = 10 t1 prioritāte = 5 t1 prioritāte pēc setPriority () = 6 tg maksimālā prioritāte pēc setMaxPriority () = 4 t1 prioritāte pēc setMaxPriority () = 6 t2 prioritāte = 4 t2 prioritāte pēc setPriority () = 4
Vītņu grupa A
(kas tg
atsauces) sākas ar augstāko prioritāti (10) kā maksimumu. Vītne X
, kura Vītne
objekts t1
atsauces, pievienojas grupai un par prioritāti saņem 5. Mēs mainām šī pavediena prioritāti uz 6, kas izdodas, jo 6 ir mazāks par 10. Pēc tam mēs piezvanām setMaxPriority (int prioritāte)
lai samazinātu grupas maksimālo prioritāti līdz 4. Lai arī pavediens X
joprojām ir 6. pievienotā prioritāte Jā
pavediens par prioritāti saņem 4. Visbeidzot, mēģinājums palielināt pavedienu Jā
Prioritāte līdz 5 neizdodas, jo 5 ir lielāka par 4.
Piezīme:setMaxPriority (int prioritāte)
automātiski pielāgo pavedienu grupas apakšgrupu maksimālo prioritāti.
Papildus pavedienu grupu izmantošanai, lai ierobežotu pavedienu prioritāti, varat veikt arī citus uzdevumus, izsaucot dažādus ThreadGroup
metodes, kas attiecas uz katras grupas pavedieniem. Metodes ietver anulēt apturēšanu ()
, anulēt atsākt ()
, anulēt pieturu ()
, un anulēt pārtraukumu ()
. Tā kā Sun Microsystems ir novecojusi pirmās trīs metodes (tās ir nedrošas), mēs tikai pārbaudām pārtraukt ()
.
Pārtrauciet pavedienu grupu
ThreadGroup
's pārtraukt ()
metode ļauj pavedienam pārtraukt noteiktas pavedienu grupas pavedienus un apakšgrupas. Šis paņēmiens izrādīsies piemērots šādā gadījumā: Jūsu lietojumprogrammas galvenais pavediens izveido vairākus pavedienus, no kuriem katrs veic darba vienību. Tā kā visiem pavedieniem ir jāpabeidz attiecīgās darba vienības, pirms kāds pavediens var pārbaudīt rezultātus, katrs pavediens gaida pēc darba vienības pabeigšanas. Galvenais pavediens uzrauga darba stāvokli. Kad visi citi pavedieni ir gaidījuši, galvenais pavediens izsauc pārtraukt ()
pārtraukt citu pavedienu gaidīšanu. Tad šie pavedieni var pārbaudīt un apstrādāt rezultātus. 3. saraksts parāda pavedienu grupas pārtraukumu:
Saraksts 3. InterruptThreadGroup.java
// InterruptThreadGroup.java klase InterruptThreadGroup {public static void main (String [] args) {MyThread mt = new MyThread (); mt.setName ("A"); mt.start (); mt = new MyThread (); mt.setName ("B"); mt.start (); izmēģiniet {Thread.sleep (2000); // Pagaidiet 2 sekundes} catch (InterruptedException e) {} // Pārtrauciet visas metodes vienā pavedienu grupā ar galveno // pavedienu Thread.currentThread () .getThreadGroup () .interrupt (); }} klase MyThread paplašina Thread {public void run () {synchronized ("A") {System.out.println (getName () + "gatavojas gaidīt."); mēģiniet {"A" .gaidiet (); } catch (InterruptedException e) {System.out.println (getName () + "pārtraukts"); } System.out.println (getName () + "beidzas"); }}}