Vícevláknové v Java
Každá aplikace může mít více procesů (instancí). Každý z těchto procesů může být přiřazen buď jako jedno vlákno, nebo jako více vláken. V tomto tutoriálu uvidíme, jak provádět více úloh současně, a také se dozvíme více o vláknech a synchronizaci mezi vlákny.
Co je Single Thread?
Jedno vlákno dovnitř Java je v podstatě lehká a nejmenší jednotka zpracování. Java používá vlákna pomocí „třídy vláken“. Existují dva typy vláken – uživatelské vlákno a vlákno démona (vlákna démonů 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 tom můžeme vytvořit mnoho uživatelských vláken a vláken démonů.
Příklad jednoho vlákna:
package demotest; public class GuruThread { public static void main(String[] args) { System.out.println("Single Thread"); } }
Výhody jednoho vlákna:
- Snižuje režii v aplikaci, protože se v systému spouští jediné vlákno
- Také to snižuje náklady na údržbu aplikace.
V čem je multithreading Java?
Vícevláknové zpracování in Java je proces spouštění dvou nebo více vláken současně pro maximální využití CPU. Vícevláknové aplikace spouštějí dvě nebo více vláken běžících současně. Proto je také známý jako Concurrency in Java. Každé vlákno probíhá vzájemně paralelně. Více vláken nevyčleňuje samostatnou oblast paměti, a proto šetří paměť. Také přepínání kontextu mezi vlákny zabere méně času.
Příklad vícevlákna:
package demotest; public class GuruThread1 implements Runnable { public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
Výhody multivlákna:
- Uživatelé nejsou blokováni, protože vlákna jsou nezávislá a můžeme provádět více operací najednou
- Jako taková jsou vlákna nezávislá, ostatní vlákna nebudou ovlivněna, pokud jedno vlákno splňuje výjimku.
Závit životního cyklu v Java
Ž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 vlákno vytvořeno pomocí třídy „Thread class“. V tomto stavu zůstává až do programu začíná vlákno. To je také známé jako rodné vlákno.
- Spustitelné: Na této stránce je instance vlákna vyvolána metodou start. Řízení vlákna je předáno plánovači, aby dokončil provádění. Záleží na plánovači, zda vlákno spustit.
- Běh: Když se vlákno začne vykonávat, stav se změní na „běžící“. Plánovač vybere jedno vlákno z fondu vláken a spustí se 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 se nespustí druhé vlákno. Proto je tento stav označován jako stav čekání.
- Mrtvý: Toto je stav, kdy je vlákno ukončeno. Vlákno je ve stavu běhu a jakmile dokončí zpracování, je v „mrtvém stavu“.
Metody multithreadingu v Java
Některé z běžně používaných metod pro vlákna jsou:Metoda | Description |
---|---|
Start() | Tato metoda spustí provádění vlákna a JVM volá metodu run() ve vláknu. |
Spánek (int milisekundy) | Tato metoda uvede vlákno do režimu spánku, takže provádění vlákna se pozastaví na poskytnuté milisekundy a poté se vlákno znovu spustí. To pomáhá při synchronizaci vláken. |
getName () | Vrací název vlákna. |
setPriority (int newpriority) | Změní prioritu vlákna. |
výnos () | Způsobí spuštění aktuálního vlákna při zastavení a dalších vláken. |
Příklad: V tomto vícevláknovém programu v Java například vytvoříme vlákno a prozkoumáme vestavěné metody dostupné pro vlákna.
package demotest; public class thread_example1 implements Runnable { @Override public void run() { } public static void main(String[] args) { Thread guruthread1 = new Thread(); guruthread1.start(); try { guruthread1.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } guruthread1.setPriority(1); int gurupriority = guruthread1.getPriority(); System.out.println(gurupriority); System.out.println("Thread Running"); } }
Vysvětlení kódu:
- 2. řádek kódu: Vytváříme třídu „thread_Example1“, která implementuje rozhraní Runnable (měla by být implementována jakoukoli třídou, jejíž instance má vlákno spouštět.)
- 4. řádek kódu: Přepíše metodu běhu spustitelného rozhraní, protože je povinné tuto metodu přepsat
- 6. řádek kódu: Zde jsme definovali hlavní metodu, ve které spustíme provádění vlákna.
- 7. řádek kódu: Zde vytváříme nový název vlákna jako „guruthread1“ vytvořením nové třídy vlákna.
- 8. řádek kódu: použijeme metodu „start“ vlákna pomocí instance „guruthread1“. Zde se vlákno začne spouštět.
- 10. řádek kódu: Zde používáme metodu „sleep“ vlákna pomocí instance „guruthread1“. Vlákno tedy přejde do režimu spánku po dobu 1000 milisekund.
- Kód 9-14: Zde jsme vložili metodu spánku do bloku try catch, protože existuje kontrolovaná výjimka, která se vyskytuje, tj. Přerušená výjimka.
- 15. řádek kódu: Zde nastavujeme prioritu vlákna na 1 podle toho, která priorita byla
- 16. řádek kódu: Zde získáváme prioritu vlákna pomocí getPriority()
- 17. řádek kódu: Zde tiskneme hodnotu načtenou z getPriority
- 18. řádek kódu: Zde píšeme text, že vlákno běží.
Když spustíte výše uvedený kód, získáte následující výstup:
Výstup:
5 je priorita vlákna a běh vlákna je text, který je výstupem našeho kódu.
Java Vlákno Synchronizace
V multithreadingu existuje asynchronní chování programů. Pokud jedno vlákno zapisuje nějaká data a jiné vlákno, které čte data současně, může to způsobit nekonzistenci v aplikaci. Když je potřeba přistupovat ke sdíleným zdrojům dvěma nebo více vlákny, pak se používá synchronizační přístup. 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 volat tuto metodu na stejném objektu. Všechna vlákna musí počkat, až vlákno dokončí synchronizovaný blok a nevyjde z něj. Tímto způsobem synchronizace pomáhá ve vícevláknové aplikaci. Jedno vlákno musí počkat, až druhé vlákno dokončí své provádění, teprve potom mohou být spuštěna ostatní vlákna.
Může být zapsán v následujícím tvaru:
Synchronized(object) { //Block of statements to be synchronized }
Vícevláknové v Java Příklady programů
V tomto multithreadingu Java například vezmeme dvě vlákna a načteme jména vlákna.
Příklad1:
GuruThread1.java package demotest; public class GuruThread1 implements Runnable{ /** * @param args */ public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
Vysvětlení kódu:
- 3. řádek kódu: Vzali jsme třídu „GuruThread1“, která implementuje Runnable (měla by být implementována libovolnou třídou, jejíž instance má vlákno spouštět.)
- 8. řádek kódu: Toto je hlavní metoda třídy
- 9. řádek kódu: Zde vytváříme instanci třídy Thread a vytváříme instanci s názvem „guruThread1“ a vytváříme vlákno.
- 10. řádek kódu: Zde vytváříme instanci třídy Thread a vytváříme instanci s názvem „guruThread2“ a vytváříme vlákno.
- 11. řádek kódu: Začínáme vlákno, tj. guruThread1.
- 12. řádek kódu: Začínáme vlákno, tj. guruThread2.
- 13. řádek kódu: Výstup textu jako „Názvy vláken jsou následující:“
- 14. řádek kódu: Získání názvu vlákna 1 pomocí metody getName() třídy vlákna.
- 15. řádek kódu: 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 vypisují jako
- Guru1
- Guru2
Příklad 2:
V tomto multithreadingu v Java například se naučíme o přepisování metod run() a start() spustitelného rozhraní a vytvoříme dvě vlákna této třídy a podle toho je spustíme.
Také chodíme na dvě třídy,
- Takový, který bude implementovat spustitelné rozhraní a
- Další, který bude mít hlavní metodu a podle toho provede.
package demotest; public class GuruThread2 { public static void main(String[] args) { // TODO Auto-generated method stub GuruThread3 threadguru1 = new GuruThread3("guru1"); threadguru1.start(); GuruThread3 threadguru2 = new GuruThread3("guru2"); threadguru2.start(); } } class GuruThread3 implements Runnable { Thread guruthread; private String guruname; GuruThread3(String name) { guruname = name; } @Override public void run() { System.out.println("Thread running" + guruname); for (int i = 0; i < 4; i++) { System.out.println(i); System.out.println(guruname); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread has been interrupted"); } } } public void start() { System.out.println("Thread started"); if (guruthread == null) { guruthread = new Thread(this, guruname); guruthread.start(); } } }
Vysvětlení kódu:
- 2. řádek kódu: Zde bereme třídu „GuruThread2“, která bude mít hlavní metodu.
- 4. řádek kódu: Zde bereme hlavní metodu třídy.
- Řádek 6–7 kódu: Zde vytváříme instanci třídy GuruThread3 (která je vytvořena v níže uvedených řádcích kódu) jako „threadguru1“ a spouštíme vlákno.
- Řádek 8–9 kódu: Zde vytváříme další instanci třídy GuruThread3 (která je vytvořena v níže uvedených řádcích kódu) jako „threadguru2“ a spouštíme vlákno.
- 11. řádek kódu: Zde vytváříme třídu „GuruThread3“, která implementuje spustitelné rozhraní (měla by být implementována libovolnou třídou, jejíž instance jsou určeny ke spouštění vláknem.)
- Řádek 13–14 kódu: bereme dvě proměnné třídy, z nichž jedna je typu thread class a druhá třídy string.
- Řádek 15–18 kódu: přepisujeme konstruktor GuruThread3, který přebírá jeden argument jako typ řetězce (což je název vlákna), který se přiřadí proměnné třídy guruname, a proto je uložen název vlákna.
- 20. řádek kódu: Zde přepisujeme metodu run() spustitelného rozhraní.
- 21. řádek kódu: Název vlákna vypisujeme pomocí příkazu println.
- Řádek 22–31 kódu: Zde používáme cyklus for s čítačem inicializovaným na 0 a nemělo by být menší než 4 (můžeme vzít libovolné číslo, proto zde cyklus proběhne 4krát) a zvyšujeme čítač. Tiskneme název vlákna a také uspáváme vlákno na 1000 milisekund v rámci bloku try-catch, protože metoda spánku vyvolala zaškrtnutou výjimku.
- 33. řádek kódu: Zde přepisujeme metodu spuštění spustitelného rozhraní.
- 35. řádek kódu: Vypisujeme text „Vlákno zahájeno“.
- Řádek 36–40 kódu: Zde bereme podmínku if, abychom zkontrolovali, zda má proměnná třídy guruthread hodnotu nebo ne. Pokud je null, pak vytváříme instanci pomocí třídy vlákna, která přebírá jméno jako parametr (hodnota, pro kterou 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:
Jsou zde tedy dvě vlákna, dostaneme dvakrát zprávu „Vlákno zahájeno“.
Názvy vláken získáme tak, jak jsme je odeslali.
Přejde do smyčky for, kde tiskneme počítadlo a název vlákna a počítadlo začíná 0.
Cyklus se provede třikrát a mezi tím vlákno spí 1000 milisekund.
Nejprve tedy dostaneme guru1, poté guru2 a poté znovu guru2, protože vlákno zde spí 1000 milisekund a poté další guru1 a znovu guru1, vlákno spí 1000 milisekund, takže dostaneme guru2 a poté guru1.
Shrnutí
V tomto tutoriálu jsme viděli vícevláknové aplikace v Java a jak používat jedno a vícevláknové v Java.
- Vysvětlete multithreading v Java: 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 synchronizace mezi vlákny, což napomáhá hladkému chodu aplikace.
- Vícevláknové programování v Java usnadňuje mnoho dalších aplikačních úloh.