CodeGym/Java blog/Véletlen/Többszálú: Mit csinálnak a Thread osztály metódusai
John Squirrels
Szint
San Francisco

Többszálú: Mit csinálnak a Thread osztály metódusai

Megjelent a csoportban
Szia! Ma továbbra is a többszálú feldolgozásról fogunk beszélni. Vizsgáljuk meg a Thread osztályt és néhány metódusát. Amikor korábban tanulmányoztuk az osztálymetódusokat, általában csak ezt írtuk: <metódus neve> -> <mit csinál a metódus>. Többszálú: Mit csinálnak a Thread osztály metódusai - 1Ez nem fog működni Thread's metódusaival :) Összetettebb logikájuk van, amit néhány példa nélkül nem fogsz kitalálni.

A Thread.start() metódus

Kezdjük önmagunk ismétlésével. Amint valószínűleg emlékszel, létrehozhat egy szálat úgy, hogy az osztály örökli az Threadosztályt, és felülírja a run()metódust. De persze nem indul el magától. Ehhez hívjuk objektumunk start()metódusát. Többszálú: Mit csinálnak a Thread osztály metódusai - 2Idézzük fel a példát az előző leckéből:
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Thread executed: " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Megjegyzés: A szál indításáhozstart()a metódus helyett a speciális metódustrun()! Ez könnyen elkövethető hiba, különösen akkor, ha először kezdi el a többszálú tanulást. Példánkban, harun()10-szer hívja meg a metódust a helyettstart(), a következőt kapja:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Tekintse meg programunk eredményét: Szál végrehajtva: Thread-0 Szál végrehajtva: Thread-1 Szál végrehajtva: Thread-2 Szál végrehajtva: Thread-3 Szál végrehajtva: Thread-4 Szál végrehajtva: Thread-5 Szál végrehajtva: Thread-6 Szál végrehajtva: Thread-7 Szál végrehajtva: Thread-8 Szál végrehajtva: Thread-9 Nézd meg a kimenet sorrendjét: Minden tökéletes rendben történik. Furcsa, mi? Nem szoktuk ezt meg, mert már tudjuk, hogy a szálak indításának és végrehajtásának sorrendjét az operációs rendszerünkön belüli felsőbbrendű intellektus határozza meg: a szálütemező. Talán csak szerencsénk volt? Persze ez nem a szerencsén múlik. Ezt úgy ellenőrizheti, hogy még néhányszor futtatja a programot. A probléma az, hogy hívja arun()metódusnak közvetlenül semmi köze a többszálú kezeléshez. Ebben az esetben a program a fő szálon fut, ugyanazon a szálon, amelyik a main()metódust is végrehajtja. Egyszerűen egymás után 10 sort nyomtat a konzolra, és kész. 10 szál még nem indult el. Tehát ne feledje ezt a jövőben, és folyamatosan ellenőrizze magát. Ha azt szeretné, hogy a run()metódus meghívásra kerüljön, hívja a start(). Menjünk tovább.

A Thread.sleep() metódus

Az aktuális szál végrehajtásának egy időre történő felfüggesztéséhez a módszert használjuk sleep(). Többszálú: Mit csinálnak a Thread osztály metódusai - 3A sleep()metódus néhány ezredmásodpercet vesz igénybe argumentumként, amely azt jelzi, hogy mennyi ideig kell a szálat aludni.
public class Main {

   public static void main(String[] args) throws InterruptedException {

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - How long did I sleep? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " seconds");

   }
}
Konzol kimenet: - Meddig aludtam? - 3 másodperc Megjegyzés: a sleep()metódus statikus: elalszik az aktuális szálat. Vagyis a jelenleg kivégzés alatt álló. Itt van még egy fontos pont: az alvó szál megszakítható. Ebben az esetben a program egy InterruptedException. Az alábbiakban egy példát veszünk figyelembe. Amúgy mi történik, miután felébred a cérna? Ott folytatódik a végrehajtás, ahol abbahagyta? Nem. Miután egy szál felébred, azaz az argumentumként eltelt idő lejárt Thread.sleep(), átvált futtathatóváállapot. Ez azonban nem jelenti azt, hogy a szálütemező futtatni fogja. Lehetséges, hogy előnyben részesít egy másik, nem alvó szálat, és hagyja, hogy frissen felébredt szálunk egy kicsit később folytassa a munkáját. Ne feledje: az ébredés nem jelenti azt, hogy azonnal folytatni kell a munkát!

A Thread.join() metódus

Többszálú: Mit csinálnak a Thread osztály metódusai - 4A join()metódus felfüggeszti az aktuális szál végrehajtását, amíg egy másik szál be nem fejeződik. Ha van 2 szálunk, t1és t2, és írunk
t1.join()
akkor t2nem indul el, amíg be t1nem fejezi a munkáját. A join()módszer használható a szálak végrehajtási sorrendjének garantálására. Nézzük meg, hogyan join()működik a módszer a következő példában:
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Thread started: " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Thread " + getName() + " is finished.");
   }
}


public class Main {

   public static void main(String[] args) throws InterruptedException {

       ThreadExample t1 = new ThreadExample();
       ThreadExample t2 = new ThreadExample();

       t1.start();


 /* The second thread (t2) will start running only after the first thread (t1)
       is finished (or an exception is thrown) */
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       // The main thread will continue running only after t1 and t2 have finished
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("All threads have finished. The program is finished.");

   }
}
Létrehoztunk egy egyszerű ThreadExampleosztályt. Feladata, hogy üzenetet jelenítsen meg, hogy elindult a szál, elalszik 5 másodpercre, majd végül jelenti a munka befejezését. Szelet torta. A fő logika az osztályban van Main. Nézze meg a megjegyzéseket: a join()metódus segítségével sikeresen kezeljük a szálak végrehajtási sorrendjét. Ha emlékszel, hogyan indítottuk el ezt a témát, a végrehajtási sorrendet a szálütemező kezeli. A szálakat saját belátása szerint futtatja: minden alkalommal más módon. Itt azt a módszert használjuk, hogy garantáljuk, hogy t1először a szál induljon el és hajtsa végre először, majd at2szál, és csak ezután folytatódik a program főszála. Továbblépni. Valódi programokban gyakran előfordul olyan helyzet, amikor meg kell szakítania egy szál végrehajtását. Például a szálunk fut, de egy bizonyos eseményre vagy feltételre vár. Ha ez megtörténik, a szál leáll. Valószínűleg lenne értelme, ha lenne valamilyen stop()módszer. De ez nem ilyen egyszerű. Valaha a Java-nak volt egy Thread.stop()metódusa, és lehetővé tette egy szál megszakítását. Később azonban eltávolították a Java könyvtárból. Megtalálhatja az Oracle dokumentációjában, és láthatja, hogy elavultként van megjelölve. Miért? Mert egyszerűen leállította a szálat anélkül, hogy bármi mást csinált volna. Például előfordulhat, hogy a szál adatokkal dolgozik, és megváltoztat valamit. Aztán munkája kellős közepén hirtelen és szertartásmentesen megszakította a stop()módszer. Megfelelő leállítás, erőforrás-felszabadítás, még hibakezelés nélkül sem volt semmi. Kissé túlzásképpen a stop()módszer egyszerűen mindent elpusztított az útjában. Olyan volt, mintha kihúzta volna a tápkábelt a konnektorból, hogy kikapcsolja a számítógépet. Igen, elérheti a kívánt eredményt. De mindenki tudja, hogy néhány hét múlva a számítógép nem fogja megköszönni, hogy így bánik vele. Ezért változott meg a szálak megszakításának logikája a Java-ban, és most egy speciális interrupt()módszert használ.

A Thread.interrupt() metódus

Mi történik, ha a interrupt()metódust egy szálon hívják meg? 2 lehetőség van:
  1. joinHa az objektum várakozó állapotban volt például a vagy metódusok miatt sleep, akkor a várakozás megszakad, és a program egy -et dob InterruptedException.
  2. Ha a szál működő állapotban volt, akkor a logikai interruptedjelző kerül az objektumra.
De ellenőriznünk kell ennek a zászlónak az értékét az objektumon, és magunktól helyesen kell elvégeznünk a munkát! Ezért Threadvan az osztályban a boolean isInterrupted()módszer. Térjünk vissza az órapéldához, amely az alaptanfolyam egyik leckében volt. A kényelem kedvéért kissé leegyszerűsítettük:
public class Clock extends Thread {

   public static void main(String[] args) throws InterruptedException {
       Clock clock = new Clock();
       clock.start();

       Thread.sleep(10000);
       clock.interrupt();
   }

   public void run() {
       Thread current = Thread.currentThread();

       while (!current.isInterrupted())
       {
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               System.out.println("The thread was interrupted");
               break;
           }
           System.out.println("Tick");
       }
   }
}
Ebben az esetben az óra elindul, és másodpercenként ketyegni kezd. A 10. másodpercben megszakítjuk az óra menetét. Amint azt már tudja, ha a megszakítani próbált szál valamelyik várakozási állapotban van, az eredmény egy InterruptedException. Ez egy ellenőrzött kivétel, így könnyen elkaphatjuk, és végrehajthatjuk a logikánkat a program befejezéséhez. És csak ezt tettük. Íme az eredményünk: Tick Tick Tick Tcik Tick Tick Tick Tick A szál megszakadt Ezzel az Threadosztály legfontosabb metódusaival kapcsolatos bemutatkozásunkat zárjuk. Sok szerencsét!
Hozzászólások
  • Népszerű
  • Új
  • Régi
Hozzászólás írásához be kell jelentkeznie
Ennek az oldalnak még nincsenek megjegyzései