Libovolná aplikace může mít více procesů (instancí). Každému z těchto procesů lze přiřadit buď jedno vlákno, nebo více vláken. V tomto tutoriálu uvidíme, jak provádět více úkolů současně a také se dozvíte více o vláknech a synchronizaci mezi vlákny.
V tomto tutoriálu se naučíme:
- Co je to jedno vlákno
- Co je to multithreading v Javě?
- Životní cyklus vlákna v Javě
- Synchronizace vláken Java
- Příklad Java Multithreading
Co je to jedno vlákno?
Jedno vlákno je v zásadě lehká a nejmenší jednotka zpracování. Java používá vlákna pomocí „třídy vláken“.
Existují dva typy podprocesů - uživatelské vlákno a daemonové vlákno (daemonové vlákna se používají, když chceme aplikaci vyčistit a používají se na pozadí).
Při prvním spuštění aplikace se vytvoří uživatelské vlákno. Po tomto můžeme vytvořit mnoho uživatelských vláken a vláken démonů.
Příklad jednoho vlákna:
balíček demotest;veřejná třída GuruThread{public static void main (String [] args) {System.out.println ("Jedno vlákno");}}
Výhody jednoho vlákna:
- Snižuje režii v aplikaci, protože se v systému provádí jedno vlákno
- Také snižuje náklady na údržbu aplikace.
Co je to multithreading v Javě?
MULTITHREADING v Javě je proces provádění dvou nebo více vláken současně k maximálnímu využití CPU. Vícevláknové aplikace spouští současně dvě nebo více podprocesů. Proto je také známý jako souběžnost v Javě. Každé vlákno běží paralelně k sobě. Vícenásobná vlákna nepřidělují samostatnou oblast paměti, a proto šetří paměť. Přepínání kontextu mezi vlákny také zabere méně času.
Příklad více vláken:
balíček demotest;veřejná třída 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áken jsou následující:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@ Přepispublic void run () {}}
Výhody vícevlákna:
- Uživatelé nejsou blokováni, protože vlákna jsou nezávislá a my můžeme provádět několik operací najednou
- Jako taková jsou vlákna nezávislá, ostatní vlákna nebudou ovlivněna, pokud jedno vlákno splní výjimku.
Životní cyklus vlákna v Javě
Životní cyklus vlákna:
Existují různé fáze životního cyklu vlákna, jak je znázorněno na obrázku výše:
- Nový
- Spustitelný
- Běh
- Čekání
- Mrtvý
- Novinka: V této fázi je nit je vytvořena pomocí třídy „Třída Thread“ zůstane .To v tomto stavu, dokud se program spustí nit. To je také známé jako rodná nit.
- Runnable: Na této stránce je instance vlákna vyvolána metodou start. Ovládání podprocesu je dáno plánovači, aby dokončil provedení. Záleží na plánovači, zda vlákno spustit.
- Spuštěno: Když se vlákno začne spouštět, stav se změní na „spuštěný“. Plánovač vybere jedno vlákno z fondu vláken a začne se spouštět v aplikaci.
- Čekání: Toto je stav, kdy vlákno musí čekat. Protože v aplikaci běží více vláken, je potřeba synchronizace mezi vlákny. Jedno vlákno tedy musí čekat, dokud nebude spuštěno druhé vlákno. Proto se tento stav označuje jako čekající.
- Mrtvý: Toto je stav, kdy je vlákno ukončeno. Vlákno je v provozním stavu a jakmile dokončí zpracování, je v „mrtvém stavu“.
Některé z běžně používaných metod pro vlákna jsou:
Metoda | Popis |
---|---|
Start() | Tato metoda spouští provádění vlákna a JVM volá metodu run () na vlákně. |
Spánek (v milisekundách) | Tato metoda umožňuje spánek podprocesu, proto se provádění podprocesu pozastaví na poskytnuté milisekundy a poté se podproces znovu spustí. Tato pomoc při synchronizaci vláken. |
getName () | Vrátí název vlákna. |
setPriority (int newpriority) | Mění prioritu vlákna. |
výnos () | Způsobí spuštění aktuálního vlákna a dalších vláken. |
Příklad: V tomto příkladu vytvoříme vlákno a prozkoumáme integrované metody dostupné pro vlákna.
balíček demotest;veřejná třída thread_example1 implementuje Runnable {@ Přepispublic void run () {}public static void main (String [] args) {Vlákno guruthread1 = nové vlákno ();guruthread1.start ();Snaž se {guruthread1.sleep (1000);} chytit (InterruptedException e) {// TODO Automaticky generovaný blok zachyceníe.printStackTrace ();}guruthread1.setPriority (1);int gurupriority = guruthread1.getPriority ();System.out.println (gurupriority);System.out.println ("vlákno spuštěno");}}
Vysvětlení kódu:
- Řádek kódu 2: Vytváříme třídu "thread_Example1", která implementuje rozhraní Runnable (mělo by být implementováno jakoukoli třídou, jejíž instance mají být vláknem provedeny.)
- Řádek kódu 4: Přepíše metodu spuštění spustitelného rozhraní, protože je povinná tuto metodu přepsat
- Řádek kódu 6: Zde jsme definovali hlavní metodu, ve které zahájíme provádění vlákna.
- Řádek kódu 7: Zde vytváříme nový název vlákna jako „guruthread1“ vytvořením instance nové třídy vlákna.
- Řádek kódu 8: použijeme metodu "start" vlákna pomocí instance "guruthread1". Zde se vlákno začne provádět.
- Řádek kódu 10: Zde používáme metodu „spánku“ vlákna pomocí instance „guruthread1“. Proto vlákno bude spát po dobu 1000 milisekund.
- Kód 9-14: Tady jsme vložili metodu spánku do bloku try catch, protože existuje zaškrtnutá výjimka, která nastane, tj. Přerušená výjimka.
- Řádek kódu 15: Zde nastavujeme prioritu vlákna na 1 z jakékoli priority
- Řádek kódu 16: Zde dostáváme prioritu vlákna pomocí getPriority ()
- Řádek kódu 17: Zde tiskneme hodnotu získanou z getPriority
- Řádek kódu 18: Zde píšeme text, který běží vlákno.
Když spustíte výše uvedený kód, získáte následující výstup:
Výstup:
5 je priorita Thread a Thread Running je text, který je výstupem našeho kódu.
Synchronizace vláken Java
V multithreadingu existuje asynchronní chování programů. Pokud jedno vlákno zapisuje některá data a jiné vlákno, které čte data současně, může v aplikaci dojít k nekonzistenci.
Když je potřeba přistupovat ke sdíleným prostředkům dvěma nebo více vlákny, použije se přístup synchronizace.
Java poskytuje synchronizované metody pro implementaci synchronizovaného chování.
V tomto přístupu, jakmile vlákno dosáhne uvnitř synchronizovaného bloku, pak žádné jiné vlákno nemůže zavolat tuto metodu na stejný objekt. Všechna vlákna musí počkat, dokud vlákno nedokončí synchronizovaný blok a nevyjde z toho.
Tímto způsobem synchronizace pomáhá ve vícevláknové aplikaci. Jedno vlákno musí počkat, až ostatní vlákno dokončí své spuštění, až poté budou povoleny další vlákna.
Může být napsán v následující podobě:
Synchronizované (objekt){// Blok výpisů, které mají být synchronizovány}
Příklad Java Multithreading
V tomto příkladu vezmeme dvě vlákna a načteme názvy vlákna.
Příklad 1:
GuruThread1.javabalíček demotest;veřejná třída 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áken jsou následující:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@ Přepispublic void run () {}}
Vysvětlení kódu:
- Řádek kódu 3: Vzali jsme třídu "GuruThread1", která implementuje Runnable (měla by být implementována jakoukoli třídou, jejíž instance mají být vláknem provedeny.)
- Řádek kódu 8: Toto je hlavní metoda třídy
- Řádek kódu 9: Zde vytváříme instanci třídy Thread a vytváříme instanci s názvem „guruThread1“ a vytváříme vlákno.
- Řádek kódu 10: Zde vytváříme instanci třídy Thread a vytváříme instanci s názvem „guruThread2“ a vytváříme vlákno.
- Řádek kódu 11: Spouštíme vlákno, tj. GuruThread1.
- Řádek kódu 12: Začínáme vlákno, tj. GuruThread2.
- Řádek kódu 13: Výstup textu jako „Názvy vláken jsou následující:“
- Řádek kódu 14: Získání názvu vlákna 1 pomocí metody getName () třídy vlákna.
- Řádek kódu 15: Získání názvu vlákna 2 pomocí metody getName () třídy vlákna.
Když spustíte výše uvedený kód, získáte následující výstup:
Výstup:
Názvy vláken se zde zobrazují jako
- Guru1
- Guru2
Příklad 2:
V tomto příkladu se dozvíme o přepsání metod run () a start () metody spustitelného rozhraní a vytvoříme dvě vlákna této třídy a odpovídajícím způsobem je spustíme.
Bereme také dvě třídy,
- Jeden, který bude implementovat spustitelné rozhraní a
- Další, který bude mít hlavní metodu a bude se podle toho provádět.
balíček demotest;veřejná třída GuruThread2 {public static void main (String [] args) {// TODO Automaticky generovaný útržek metodyGuruThread3 threadguru1 = nový GuruThread3 ("guru1");threadguru1.start ();GuruThread3 threadguru2 = nový GuruThread3 ("guru2");threadguru2.start ();}}třída GuruThread3 implementuje Runnable {Závitový guruthread;soukromý řetězec guruname;GuruThread3 (název řetězce) {guruname = jméno;}@ Přepispublic void run () {System.out.println ("Thread running" + guruname);pro (int i = 0; i <4; i ++) {System.out.println (i);System.out.println (guruname);Snaž se {Závit. Spánek (1000);} chytit (InterruptedException e) {System.out.println ("Vlákno bylo přerušeno");}}}public void start () {System.out.println ("Thread started");if (guruthread == null) {guruthread = nové vlákno (toto, guruname);guruthread.start ();}}}
Vysvětlení kódu:
- Řádek kódu 2: Zde používáme třídu „GuruThread2“, která bude obsahovat hlavní metodu.
- Řádek kódu 4: Zde používáme hlavní metodu třídy.
- Řádek kódu 6-7: Zde vytváříme instanci třídy GuruThread3 (která je vytvořena v níže uvedených řádcích kódu) jako „threadguru1“ a začínáme vlákno.
- Řádek kódu 8-9: Zde vytváříme další instanci třídy GuruThread3 (která je vytvořena v následujících řádcích kódu) jako „threadguru2“ a začínáme vlákno.
- Řádek kódu 11: Zde vytváříme třídu „GuruThread3“, která implementuje spustitelné rozhraní (měla by být implementována jakoukoli třídou, jejíž instance mají být spuštěny vláknem.)
- Řádek kódu 13-14: vezmeme dvě proměnné třídy, z nichž jedna je třídy typu vlákna a druhá třídy řetězce.
- Řádek kódu 15-18: přepisujeme konstruktor GuruThread3, který bere jeden argument jako typ řetězce (což je název vlákna), který se přiřadí k proměnné třídy guruname, a proto se název vlákna uloží.
- Řádek kódu 20: Zde přepisujeme metodu run () spustitelného rozhraní.
- Řádek kódu 21: Název vlákna vydáváme pomocí příkazu println.
- Řádek kódu 22-31: Zde používáme smyčku for s počitadlem inicializovaným na 0 a nemělo by být menší než 4 (můžeme vzít libovolné číslo, proto zde smyčka poběží 4krát) a zvyšování čítače. Tiskneme název podprocesu a také děláme spánek podprocesu po dobu 1000 milisekund v bloku try-catch, protože metoda spánku vyvolala kontrolovanou výjimku.
- Řádek kódu 33: Zde přepisujeme metodu spuštění spustitelného rozhraní.
- Řádek kódu 35: Na výstupu je text „Thread started“.
- Řádek kódu 36-40: Zde bereme podmínku if, abychom zkontrolovali, zda má proměnná třídy guruthread v sobě hodnotu nebo ne. Pokud má hodnotu null, vytváříme instanci pomocí třídy vlákna, která bere název jako parametr (hodnota, která byla přiřazena v konstruktoru). Poté se vlákno spustí pomocí metody start ().
Když spustíte výše uvedený kód, získáte následující výstup:
Výstup :
Existují tedy dvě vlákna, takže se nám dvakrát zobrazí zpráva „Thread started“.
Získáváme názvy podprocesů tak, jak jsme je odeslali.
Jde do smyčky for, kde tiskneme název čítače a vlákna a počitadlo začíná na 0.
Smyčka se provede třikrát a mezi vláknem se usne po dobu 1000 milisekund.
Proto nejprve dostaneme guru1, pak guru2, pak znovu guru2, protože vlákno zde spí po dobu 1000 milisekund a pak další guru1 a znovu guru1, vlákno spí po dobu 1000 milisekund, takže dostaneme guru2 a poté guru1.
Shrnutí :
V tomto kurzu jsme viděli vícevláknové aplikace v Javě a jak používat jedno a více vláken.
- V multithreadingu nejsou uživatelé blokováni, protože vlákna jsou nezávislá a mohou provádět více operací najednou
- Různé fáze životního cyklu vlákna jsou,
- Nový
- Spustitelný
- Běh
- Čekání
- Mrtvý
- Také jsme se dozvěděli o synchronizaci mezi vlákny, které pomáhají hladkému chodu aplikace.
- Vícevláknové zpracování usnadňuje mnohem více aplikačních úkolů.