Akákoľvek aplikácia môže mať viac procesov (inštancií). Každému z týchto procesov je možné priradiť jedno vlákno alebo viac vlákien. Uvidíme v tomto tutoriáli, ako vykonávať viac úloh súčasne a tiež sa dozvieme viac o vláknach a synchronizácii medzi vláknami.
V tomto tutoriále sa dozvieme:
- Čo je to jedno vlákno
- Čo je to multithreading v Jave?
- Životný cyklus vlákna v Jave
- Synchronizácia vlákna Java
- Príklad Java Multithreading
Čo je to jedno vlákno?
Jedno vlákno je v podstate ľahká a najmenšia jednotka spracovania. Java používa vlákna pomocou „triedy vlákien“.
Existujú dva typy vlákien - užívateľské vlákno a démonové vlákna (démonové vlákna sa používajú, keď chceme vyčistiť aplikáciu a používajú sa na pozadí).
Pri prvom spustení aplikácie sa vytvorí užívateľské vlákno. Po tomto príspevku môžeme vytvoriť veľa používateľských vlákien a vlákien démonov.
Príklad jedného vlákna:
balíček demotest;verejná trieda GuruThread{public static void main (String [] args) {System.out.println ("Jedno vlákno");}}
Výhody jedného vlákna:
- Znižuje réžiu v aplikácii ako vykonávanie jedného vlákna v systéme
- Znižuje tiež náklady na údržbu aplikácie.
Čo je to multithreading v Jave?
MULTITHREADING v Jave je proces vykonávania dvoch alebo viacerých vlákien súčasne za účelom maximálneho využitia CPU. Viacvláknové aplikácie spúšťajú súčasne dve alebo viac vlákien. Preto je tiež známy ako súbežnosť v Jave. Každé vlákno prebieha navzájom rovnobežne. Viacnásobné vlákna neprideľujú samostatnú oblasť pamäte, a preto šetria pamäť. Tiež prepínanie kontextu medzi vláknami trvá menej času.
Príklad viacvlákna:
balíček demotest;verejná trieda GuruThread1 implementuje Runnable{public static void main (String [] args) {Vlákno guruThread1 = nové vlákno ("Guru1");Vlákno guruThread2 = nové vlákno ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Názvy vlákien sú nasledujúce:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@ Overridepublic void run () {}}
Výhody multithread:
- Používatelia nie sú blokovaní, pretože vlákna sú nezávislé a my môžeme súčasne vykonávať viac operácií
- Vlákna sú teda nezávislé, ostatné vlákna nebudú ovplyvnené, ak jedno vlákno spĺňa výnimku.
Životný cyklus vlákna v Jave
Životný cyklus vlákna:
Ako je znázornené na obrázku vyššie, existujú rôzne etapy životného cyklu vlákna:
- Nový
- Spustiteľné
- Beží
- Čaká sa
- Mŕtvy
- Nové: V tejto fáze sa vlákno vytvára pomocou triedy „Trieda vlákna“. V tomto stave zostáva, kým program vlákno nespustí . Je tiež známa ako rodená niť.
- Spustiteľné: Na tejto stránke je inštancia vlákna vyvolaná metódou spustenia. Ovládanie vlákna je dané plánovaču na dokončenie vykonania. Závisí od plánovača, či vlákno spustí.
- Spustené: Keď sa vlákno začne vykonávať, stav sa zmení na stav „spustený“. Plánovač vyberie jedno vlákno z fondu vlákien a začne sa vykonávať v aplikácii.
- Čakanie: Toto je stav, keď vlákno musí čakať. Pretože v aplikácii beží viac vlákien, je medzi nimi nutná synchronizácia. Jedno vlákno teda musí čakať, kým sa vykoná druhé vlákno. Preto sa tento stav označuje ako stav čakajúci.
- Mŕtvy: Toto je stav, keď je vlákno ukončené. Vlákno je v spustenom stave a hneď ako dokončí spracovanie, je v „mŕtvom stave“.
Niektoré z bežne používaných metód pre vlákna sú:
Metóda | Popis |
---|---|
štart () | Táto metóda začína vykonávanie vlákna a JVM volá metódu run () na vlákne. |
Spánok (v milisekundách) | Táto metóda prepne vlákno do režimu spánku, preto sa vykonávanie vlákna pozastaví na poskytnuté milisekundy a potom sa vlákno opäť začne vykonávať. To pomáha pri synchronizácii vlákien. |
getName () | Vráti názov vlákna. |
setPriority (int newpriority) | Mení prioritu vlákna. |
výnos () | Spôsobí spustenie aktuálneho vlákna a ďalších vlákien. |
Príklad: V tomto príklade vytvoríme vlákno a preskúmame vstavané metódy dostupné pre vlákna.
balíček demotest;verejná trieda thread_example1 implementuje Runnable {@ Overridepublic void run () {}public static void main (String [] args) {Vlákno guruthread1 = nové vlákno ();guruthread1.start ();skúsiť {guruthread1.sleep (1000);} úlovok (InterruptedException e) {// TODO Automaticky generovaný blok úlovkove.printStackTrace ();}guruthread1.setPriority (1);int gurupriority = guruthread1.getPriority ();System.out.println (gurupriority);System.out.println ("vlákno beží");}}
Vysvetlenie kódu:
- 2. riadok kódu: Vytvárame triedu „thread_Example1“, ktorá implementuje rozhranie Runnable (mala by byť implementovaná každou triedou, ktorej inštancie má vlákno vykonávať.)
- Riadok kódu 4: Prepíše spustenú metódu spustiteľného rozhrania, pretože je povinná prepísať túto metódu
- Riadok kódu 6: Tu sme definovali hlavnú metódu, ktorou začneme vykonávanie vlákna.
- Riadok kódu 7: Tu vytvárame inštanciou novej triedy vlákna nový názov vlákna ako „guruthread1“.
- Riadok kódu 8: použijeme metódu "start" vlákna pomocou inštancie "guruthread1". Tu sa vlákno začne vykonávať.
- Riadok kódu 10: Tu používame metódu „spánku“ vlákna pomocou inštancie „guruthread1“. Preto bude vlákno spať 1000 milisekúnd.
- Kód 9-14: Tu sme vložili metódu spánku do bloku try catch, pretože je zaškrtnutá výnimka, ktorá sa vyskytne, tj. Prerušená výnimka.
- Riadok kódu 15: Tu nastavujeme prioritu vlákna na 1 z akejkoľvek priority
- Riadok kódu 16: Tu dostávame prioritu vlákna pomocou funkcie getPriority ()
- Riadok kódu 17: Tu tlačíme hodnotu načítanú z getPriority
- Riadok kódu 18: Tu píšeme text, ktorý vlákno beží.
Po vykonaní vyššie uvedeného kódu získate nasledujúci výstup:
Výkon:
5 je priorita vlákna a beh vlákna je text, ktorý je výstupom nášho kódu.
Synchronizácia vlákna Java
Pri multithreadingu existuje asynchrónne správanie programov. Ak jedno vlákno zapisuje niektoré údaje a iné vlákno, ktoré číta dáta súčasne, môže to v aplikácii spôsobiť nekonzistenciu.
Ak existuje potreba prístupu k zdieľaným prostriedkom pomocou dvoch alebo viacerých vlákien, použije sa prístup synchronizácie.
Java poskytuje synchronizované metódy na implementáciu synchronizovaného správania.
V tomto prístupe, akonáhle vlákno dosiahne vnútri synchronizovaného bloku, potom žiadne iné vlákno nemôže zavolať túto metódu na rovnakom objekte. Všetky vlákna musia počkať, kým vlákno nedokončí synchronizovaný blok a nevyjde z neho.
Týmto spôsobom pomáha synchronizácia vo viacvláknovej aplikácii. Jedno vlákno musí čakať, kým iné vlákno nedokončí svoje vykonávanie, až potom môžu vykonávať ďalšie vlákna.
Môže byť napísané v tejto podobe:
Synchronizované (objekt){// Blok výpisov, ktoré sa majú synchronizovať}
Príklad Java Multithreading
V tomto príklade vezmeme dve vlákna a načítame názvy vlákna.
Príklad 1:
GuruThread1.javabalíček demotest;verejná trieda GuruThread1 implementuje Runnable {/ *** @param args* /public static void main (String [] args) {Vlákno guruThread1 = nové vlákno ("Guru1");Vlákno guruThread2 = nové vlákno ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Názvy vlákien sú nasledujúce:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@ Overridepublic void run () {}}
Vysvetlenie kódu:
- 3. riadok kódu: Použili sme triedu „GuruThread1“, ktorá implementuje funkciu Runnable (mala by byť implementovaná každou triedou, ktorej inštancie má vlákno vykonávať.)
- Riadok kódu 8: Toto je hlavná metóda triedy
- Riadok kódu 9: Tu vytvárame inštancie triedy Thread a vytvárame inštanciu s názvom „guruThread1“ a vytvárame vlákno.
- Riadok kódu 10: Tu vytvárame inštancie triedy Thread a vytvárame inštanciu s názvom „guruThread2“ a vytvárame vlákno.
- Riadok kódu 11: Začíname vlákno, tj. GuruThread1.
- 12. riadok kódu: Začíname vlákno, tj. GuruThread2.
- Riadok kódu 13: Výstup textu ako „Názvy vlákien sú nasledujúce:“
- Riadok kódu 14: Získanie názvu vlákna 1 pomocou metódy getName () triedy vlákna.
- Riadok kódu 15: Získanie názvu vlákna 2 pomocou metódy getName () triedy vlákna.
Po vykonaní vyššie uvedeného kódu získate nasledujúci výstup:
Výkon:
Názvy vlákien sa tu zobrazujú ako
- Guru1
- Guru2
Príklad 2:
V tomto príklade sa dozvieme o prepísaní metód run () a start () metódy spustiteľného rozhrania a vytvoríme dve vlákna tejto triedy a podľa toho ich spustíme.
Berieme tiež dve triedy,
- Jeden, ktorý bude implementovať spustiteľné rozhranie a
- Ďalšia, ktorá bude mať hlavnú metódu a bude sa podľa nej vykonávať.
balíček demotest;verejná trieda GuruThread2 {public static void main (String [] args) {// TODO Automaticky generovaný pahýl metódyGuruThread3 threadguru1 = nový GuruThread3 ("guru1");threadguru1.start ();GuruThread3 threadguru2 = nový GuruThread3 ("guru2");threadguru2.start ();}}trieda GuruThread3 implementuje Runnable {Závitový guruthread;súkromný reťazec guruname;GuruThread3 (názov reťazca) {guruname = meno;}@ Overridepublic void run () {System.out.println ("Thread running" + guruname);pre (int i = 0; i <4; i ++) {System.out.println (i);System.out.println (guruname);skúsiť {Závit. Spánok (1 000);} úlovok (InterruptedException e) {System.out.println ("Vlákno bolo prerušené");}}}public void start () {System.out.println ("Vlákno spustené");if (guruthread == null) {guruthread = nové vlákno (toto, guruname);guruthread.start ();}}}
Vysvetlenie kódu:
- 2. riadok kódu: Tu používame triedu „GuruThread2“, ktorá bude obsahovať hlavnú metódu.
- Riadok kódu 4: Tu preberáme hlavnú metódu triedy.
- Riadok kódu 6-7: Tu vytvárame inštanciu triedy GuruThread3 (ktorá je vytvorená v nasledujúcich riadkoch kódu) ako „threadguru1“ a začíname vlákno.
- Riadok kódu 8-9: Tu vytvárame ďalšiu inštanciu triedy GuruThread3 (ktorá je vytvorená v ďalších riadkoch kódu) ako „threadguru2“ a začíname vlákno.
- Riadok kódu 11: Tu vytvárame triedu „GuruThread3“, ktorá implementuje spustiteľné rozhranie (mala by byť implementovaná akoukoľvek triedou, ktorej inštancie sú určené na vykonanie týmto vláknom.)
- Riadok kódu 13-14: berieme dve premenné triedy, z ktorých jedna je triedy vlákien typu a druhá triedy reťazcov.
- Riadok kódu 15-18: prepíšeme konštruktor GuruThread3, ktorý berie jeden argument ako typ reťazca (čo je názov vlákna), ktorý sa priradí k premennej triedy guruname, a preto sa uloží názov vlákna.
- Riadok kódu 20: Tu prekonávame metódu run () spustiteľného rozhrania.
- Riadok kódu 21: Názov vlákna odosielame pomocou príkazu println.
- Riadok kódu 22-31: Tu používame slučku for s počítadlom inicializovaným na 0 a nemalo by byť menšie ako 4 (môžeme vziať ľubovoľné číslo, takže tu bude slučka bežať 4 krát) a zvyšovať počítadlo. Tlačíme názov vlákna a tiež zaisťujeme, aby vlákno spalo 1000 milisekúnd v rámci bloku try-catch, pretože metóda spánku vyvolala kontrolovanú výnimku.
- Riadok kódu 33: Tu prepíšeme metódu spustenia spustiteľného rozhrania.
- Riadok kódu 35: Na výstupe je text „Vlákno začalo“.
- Riadok kódu 36-40: Tu berieme podmienku if na kontrolu toho, či má premenná triedy guruthread hodnotu alebo nie. Ak má hodnotu null, vytvárame inštanciu pomocou triedy vlákna, ktorá berie meno ako parameter (hodnota, ktorej bola priradená v konštruktore). Potom sa vlákno spustí pomocou metódy start ().
Po vykonaní vyššie uvedeného kódu získate nasledujúci výstup:
Výstup :
Existujú teda dve vlákna, dvakrát sa nám zobrazí správa „Vlákno začalo“.
Získame názvy vlákien tak, ako sme ich vytvorili.
Pôjde do cyklu for, kde tlačíme názov počítadla a vlákna a počitadlo začína nulou.
Smyčka sa vykoná trikrát a medzi vláknami sa uspáva 1 000 milisekúnd.
Preto najskôr dostaneme guru1, potom guru2, potom opäť guru2, pretože vlákno tu spí 1000 milisekúnd a potom ďalšie guru1 a opäť guru1, vlákno spí 1000 milisekúnd, takže dostaneme guru2 a potom guru1.
Zhrnutie :
V tomto tutoriáli sme videli viacvláknové aplikácie v Jave a ako používať jedno a viacvláknové vlákna.
- V multithreadingu nie sú používatelia blokovaní, pretože vlákna sú nezávislé a môžu vykonávať viac operácií naraz
- Rôzne etapy životného cyklu vlákna sú,
- Nový
- Spustiteľné
- Beží
- Čaká sa
- Mŕtvy
- Dozvedeli sme sa tiež o synchronizácii medzi vláknami, ktoré umožňujú bezproblémový chod aplikácie.
- Viacvláknový proces uľahčuje oveľa viac aplikačných úloh.