Multithreading v Java Tutorial s příklady

Obsah:

Anonim

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:

  1. Nový
  2. Spustitelný
  3. Běh
  4. Čekání
  5. Mrtvý
  1. 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.
  2. 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.
  3. 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.
  4. Č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í.
  5. 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ů.