Többszálú bemenet Java


Minden alkalmazásnak több folyamata (példánya) is lehet. Mindegyik folyamat hozzárendelhető egyetlen szálként vagy több szálként. Ebben az oktatóanyagban látni fogjuk, hogyan hajthat végre több feladatot egyidejűleg, valamint többet megtudhatunk a szálakról és a szálak közötti szinkronizálásról.

Mi az az egyszál?

Egy szál be Java alapvetően egy könnyű és a legkisebb feldolgozási egység. Java szálakat használ a „szálosztály” használatával. Kétféle szál létezik - felhasználói szál és démonszál (a démonszálakat akkor használjuk, amikor meg akarjuk tisztítani az alkalmazást, és a háttérben használatosak). Az alkalmazás első indításakor létrejön a felhasználói szál. Ezt követően sok felhasználói szálat és démonszálat hozhatunk létre.

Példa egyszálra:

package demotest;

public class GuruThread
{
       public static void main(String[] args) {
              System.out.println("Single Thread");
       }
}

Az egyszál előnyei:

  • Csökkenti az alkalmazás többletköltségét, mivel egyetlen szál fut a rendszerben
  • Ezenkívül csökkenti az alkalmazás karbantartási költségeit.

Mi az a Multithreading Java?

Többszálas in Java két vagy több szál egyidejű végrehajtásának folyamata a CPU maximális kihasználása érdekében. A többszálú alkalmazások két vagy több szálat hajtanak végre párhuzamosan. Ezért a Concurrency in néven is ismert Java. Mindegyik szál párhuzamosan fut egymással. Több szál nem foglal le külön memóriaterületet, így memóriát takarít meg. Ezenkívül a szálak közötti kontextusváltás kevesebb időt vesz igénybe.

Példa több szálra:

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() {
    }
}

A többszál előnyei:

  • A felhasználók nincsenek blokkolva, mert a szálak függetlenek, és időnként több műveletet is végrehajthatunk
  • Mivel a szálak függetlenek, a többi szálat nem érinti, ha az egyik szál kivételt tesz.

A szál életciklusa be Java

Egy szál életciklusa:

A szál életciklusa be Java
A szál életciklusa be Java

A szál életciklusának különböző szakaszai vannak, amint az a fenti ábrán látható:

  1. Újszerű
  2. futtatható
  3. futás
  4. Várakozás
  5. Halott
  1. Új: Ebben a fázisban a szál a „Thread class” osztály használatával jön létre. Ebben az állapotban marad a programig kezdődik a fonalat. Született fonalnak is nevezik.
  2. Futtatható: Ezen az oldalon a szál példányát indító metódussal hívják meg. A szálvezérlést az ütemező kapja meg a végrehajtás befejezéséhez. Az ütemezőtől függ, hogy futtatja-e a szálat.
  3. Futás: Amikor a szál elindul, az állapot „futó” állapotra változik. Az ütemező kiválaszt egy szálat a szálkészletből, és elindul az alkalmazásban.
  4. Várakozás: Ez az az állapot, amikor egy szálnak várnia kell. Mivel több szál fut az alkalmazásban, szükség van a szálak közötti szinkronizálásra. Ezért az egyik szálnak várnia kell, amíg a másik szál végrehajtásra kerül. Ezért ezt az állapotot várakozási állapotnak nevezik.
  5. Halott: Ez az az állapot, amikor a szál véget ér. A szál futó állapotban van, és amint befejezte a feldolgozást, „holt állapotba” kerül.


A többszálú beépítés módszerei Java

A szálakhoz gyakran használt módszerek közül néhány:

Módszer Leírás
Rajt() Ez a metódus elindítja a szál végrehajtását és JVM meghívja a run() metódust a szálon.
Alvás (milliszekundum) Ez a módszer alvó állapotba helyezi a szálat, így a szál végrehajtása ezredmásodpercekre szünetel, majd ezután a szál ismét elindul. Ez segít a szálak szinkronizálásában.
getName () Visszaadja a szál nevét.
setPriority (int newpriority) Megváltoztatja a szál prioritását.
hozam () Ez leállítja az aktuális szálat és a többi szál végrehajtását.

Példa: Ebben a többszálú programban be Java Például létrehozunk egy szálat, és megvizsgáljuk a szálak számára elérhető beépített módszereket.

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");
  }
}

A kód magyarázata:

  • 2. kódsor: Létrehozunk egy „thread_Example1” osztályt, amely megvalósítja a Runnable interfészt (minden olyan osztálynak meg kell valósítania, amelynek példányait a szál végre kívánja hajtani.)
  • 4. kódsor: Felülbírálja a futtatható felület futtatási módját, mivel ezt a metódust kötelező felülbírálni
  • 6. kódsor: Itt definiáltuk azt a fő módszert, amellyel elindítjuk a szál végrehajtását.
  • 7. kódsor: Itt egy új szálnevet hozunk létre „guruthread1” néven a szál új osztályának példányosításával.
  • 8. kódsor: a „guruthread1” példányt használó szál „start” metódusát fogjuk használni. Itt elindul a szál végrehajtása.
  • 10. kódsor: Itt a szál „alvó” metódusát használjuk a „guruthread1” példány használatával. Ezért a szál 1000 ezredmásodpercig aludni fog.
  • 9-14 kód: Itt az alvás módszert helyeztük a try catch blokkba, mivel van ellenőrzött kivétel, ami előfordul, azaz megszakított kivétel.
  • 15. kódsor: Itt a szál prioritását 1-re állítjuk, attól függően, hogy melyik prioritás volt
  • 16. kódsor: Itt kapjuk meg a szál prioritását a getPriority() segítségével
  • 17. kódsor: Itt kinyomtatjuk a getPriority szolgáltatásból beolvasott értéket
  • 18. kódsor: Itt egy szöveget írunk, amely folyamatban van.

Amikor végrehajtja a fenti kódot, a következő kimenetet kapja:

Szálpélda be Java

output:

Az 5 a szál prioritása, és a Thread Running a szöveg, amely a kódunk kimenete.

Java Szál Synchronizálás

A többszálú feldolgozásnál a programok aszinkron viselkedése van. Ha az egyik szál bizonyos adatokat ír, és egy másik szál egyidejűleg olvas adatokat, az inkonzisztenciát okozhat az alkalmazásban. Ha két vagy több szálon kell elérni a megosztott erőforrásokat, akkor szinkronizálási megközelítést alkalmazunk. Java szinkronizált módszereket biztosított a szinkronizált viselkedés megvalósításához.

Ebben a megközelítésben, ha a szál eléri a szinkronizált blokkot, akkor egyetlen másik szál sem hívhatja meg ezt a metódust ugyanazon az objektumon. Minden szálnak meg kell várnia, amíg az adott szál befejezi a szinkronizált blokkot, és kijön belőle. Ily módon a szinkronizálás segít egy többszálú alkalmazásban. Az egyik szálnak meg kell várnia, amíg a másik szál befejezi a végrehajtást, csak ezután engedélyezi a többi szál végrehajtását.

A következő formában írható:

Synchronized(object)
{  
        //Block of statements to be synchronized
}

Többszálú bemenet Java Példa programok

Ebben a többszálú Java Például veszünk két szálat, és lekérjük a szál nevét.

Example1:

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() {
    }
}

A kód magyarázata:

  • 3. kódsor: Vegyünk egy „GuruThread1” osztályt, amely megvalósítja a Runnable-t (ezt minden olyan osztálynak meg kell valósítania, amelynek példányait a szálnak végre kell hajtania.)
  • 8. kódsor: Ez az osztály fő módszere
  • 9. kódsor: Itt példányosítjuk a Thread osztályt, létrehozunk egy „guruThread1” nevű példányt, és létrehozunk egy szálat.
  • 10. kódsor: Itt példányosítjuk a Thread osztályt, létrehozunk egy „guruThread2” nevű példányt, és létrehozunk egy szálat.
  • 11. kódsor: Elindítjuk a szálat, azaz a guruThread1-et.
  • 12. kódsor: Elindítjuk a szálat, azaz a guruThread2-et.
  • 13. kódsor: A szöveg kiírása a következőképpen: „A szálnevek a következők:
  • 14. kódsor: Az 1. szál nevének lekérése a szálosztály getName() metódusával.
  • 15. kódsor: Az 2. szál nevének lekérése a szálosztály getName() metódusával.

Amikor végrehajtja a fenti kódot, a következő kimenetet kapja:

Java Többszálú példa

output:

A szálnevek a következőképpen jelennek meg:

  • Guru1
  • Guru2

Példa 2:

Ebben a többszálú bemenetben Java Például megtanuljuk a futtatható felület run() és start() metódusainak felülbírálását, és létrehozunk két szálat az adott osztályból, és ennek megfelelően futtatjuk őket.

Ezenkívül két osztályt veszünk,

  • Az egyik, amely megvalósítja a futtatható felületet és
  • Egy másik, amely rendelkezik a fő módszerrel, és ennek megfelelően hajtja végre.
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();
  }
 }
}

A kód magyarázata:

  • 2. kódsor: Itt egy „GuruThread2” osztályt veszünk, amelyben benne lesz a fő metódus.
  • 4. kódsor: Itt az osztály egyik fő módszerét vesszük figyelembe.
  • 6-7. kódsor: Itt létrehozzuk a GuruThread3 osztály egy példányát (amely a kód alatti soraiban jön létre) „threadguru1” néven, és elindítjuk a szálat.
  • 8-9. kódsor: Itt létrehozzuk a GuruThread3 osztály egy másik példányát (amely a kód alatti sorokban jön létre) „threadguru2” néven, és elindítjuk a szálat.
  • 11. kódsor: Itt egy „GuruThread3” osztályt hozunk létre, amely megvalósítja a futtatható felületet (minden olyan osztálynak meg kell valósítania, amelynek példányait a szál végre kívánja hajtani.)
  • 13-14. kódsor: két osztályváltozót veszünk, amelyek közül az egyik a szál osztályú, a másik pedig a string osztályú.
  • 15-18. kódsor: felülírjuk a GuruThread3 konstruktort, amely egy argumentumot vesz fel karakterlánctípusként (ami a szálak neve), amely a guruname osztályváltozóhoz lesz hozzárendelve, és így a szál neve tárolódik.
  • 20. kódsor: Itt felülírjuk a futtatható felület run() metódusát.
  • 21. kódsor: A szál nevét a println utasítással adjuk ki.
  • 22-31. kódsor: Itt egy for ciklust használunk, amelynek a számlálója 0-ra van inicializálva, és nem lehet kevesebb 4-nél (bármilyen számot vehetünk, ezért itt a ciklus 4-szer fut), és növeljük a számlálót. Kinyomtatjuk a szál nevét, és egy try-catch blokkon belül 1000 ezredmásodpercig alvó állapotba helyezzük a szálat, mivel az alvásmódszer felvetett ellenőrzött kivételt.
  • 33. kódsor: Itt felülírjuk a futtatható felület indítási módszerét.
  • 35. kódsor: A „Téma elkezdődött” szöveget adjuk ki.
  • 36-40. kódsor: Itt egy if feltételt veszünk annak ellenőrzésére, hogy a guruthread osztályváltozónak van-e értéke, vagy sem. Ha nulla, akkor egy példányt hozunk létre a szálosztály használatával, amely paraméterként veszi a nevet (amelynek értéke a konstruktorban volt hozzárendelve). Ezután a szál elindul a start() metódussal.

Amikor végrehajtja a fenti kódot, a következő kimenetet kapja:

Többszálú példa in Java

teljesítmény:

Két szál van tehát, kétszer kapjuk a „Téma elkezdődött” üzenetet.

A szál nevét úgy kapjuk meg, ahogyan kiadtuk őket.

Bemegy a for ciklusba, ahol a számlálót és a szál nevét nyomtatjuk, és a számláló 0-val kezdődik.

A ciklus háromszor hajtódik végre, és a szál között 1000 ezredmásodpercig alszik.

Ezért először a guru1-et, majd a guru2-t, majd a guru2-t kapjuk, mert a szál itt alszik 1000 ezredmásodpercig, majd a következő guru1 és ismét guru1, a szál 1000 ezredmásodpercig alszik, így kapjuk a guru2-t, majd a guru1-et.

Összegzésként

Ebben az oktatóanyagban többszálú alkalmazásokat láthattunk Java és hogyan kell használni az egy- és többszálat Java.

  • Magyarázza el a többszálú bemenetet Java: a többszálú kezelésben a felhasználók nincsenek blokkolva, mivel a szálak függetlenek, és egyszerre több műveletet is végrehajthatnak
  • A szál életciklusának különböző szakaszai:
    • Újszerű
    • futtatható
    • futás
    • Várakozás
    • Halott
  • Megtudtuk azt is összehangolás szálak között, ami segíti az alkalmazás zökkenőmentes működését.
  • Többszálú programozás Java sokkal több alkalmazási feladatot könnyít meg.