CodeGym /Java blogg /SlumpmÀssig /Multithreading: Vad metoderna i klassen Thread gör
John Squirrels
NivÄ
San Francisco

Multithreading: Vad metoderna i klassen Thread gör

Publicerad i gruppen
Hej! Idag ska vi fortsÀtta att prata om multithreading. LÄt oss undersöka klassen Thread och vad nÄgra av dess metoder gör. NÀr vi tidigare studerat klassmetoder skrev vi oftast bara detta: <metodnamn> -> <vad metoden gör>. Multithreading: Vad metoderna i Thread-klassen gör - 1Detta kommer inte att fungera med Thread's metoder :) De har mer komplex logik som du inte kommer att kunna lista ut utan nÄgra exempel.

Metoden Thread.start()

LÄt oss börja med att upprepa oss sjÀlva. Som du sÀkert minns kan du skapa en trÄd genom att fÄ din klass att Àrva klassen Threadoch ÄsidosÀtta run()metoden. Men det startar inte sjÀlvklart. För att göra detta kallar vi vÄrt objekts start()metod. Multithreading: Vad metoderna i Thread-klassen gör - 2LÄt oss komma ihÄg exemplet frÄn föregÄende lektion:

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();
       }
   }
}
Obs: För att starta en trÄd mÄste du anropa specialmetodenstart()snarare Ànrun()metoden! Detta Àr ett lÀtt fel att göra, speciellt nÀr du först börjar studera multithreading. I vÄrt exempel, om du anroparrun()metoden 10 gÄnger istÀllet förstart(), skulle du fÄ detta:

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Titta pÄ resultatet av vÄrt program: TrÄd utförd: TrÄd-0 TrÄd utförd: TrÄd-1 TrÄd utförd: TrÄd-2 TrÄd utförd: TrÄd-3 TrÄd utförd: TrÄd-4 TrÄd utförd: TrÄd-5 TrÄd utförd: TrÄd-6 TrÄd utförd: TrÄd-7 TrÄd utförd: TrÄd-8 TrÄd utförd: TrÄd-9 Titta pÄ ordningen för utdata: Allt hÀnder i perfekt ordning. Konstigt va? Vi Àr inte vana vid detta, eftersom vi redan vet att ordningen i vilken trÄdar startas och körs bestÀms av en överlÀgsen intellekt i vÄrt operativsystem: trÄdschemalÀggaren. Vi kanske bara hade tur? Naturligtvis handlar det inte om tur. Du kan verifiera detta genom att köra programmet ett par gÄnger till. Problemet Àr att ringarun()Metoden har direkt inget med multithreading att göra. I det hÀr fallet kommer programmet att köras pÄ huvudtrÄden, samma trÄd som kör metoden main(). Den skriver helt enkelt ut 10 rader pÄ konsolen successivt och det Àr allt. 10 trÄdar har inte startat. SÄ kom ihÄg detta i framtiden och kontrollera dig sjÀlv hela tiden. Om du vill att run()metoden ska anropas, ring start(). LÄt oss gÄ lÀngre.

Metoden Thread.sleep()

För att avbryta exekveringen av den aktuella trÄden ett tag anvÀnder vi sleep()metoden. Multithreading: Vad metoderna i Thread-klassen gör - 3Metoden sleep()tar ett antal millisekunder som ett argument, vilket anger hur lÄng tid det tar att lÀgga trÄden i vilolÀge.

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

   }
}
KonsolutgÄng: - Hur lÀnge sov jag? - 3 sekunder Obs: metoden sleep()Àr statisk: den sover den aktuella trÄden. Det vill sÀga den som för nÀrvarande avrÀttas. HÀr Àr en annan viktig punkt: en sovande trÄd kan avbrytas. I det hÀr fallet kastar programmet en InterruptedException. Vi kommer att övervÀga ett exempel nedan. Förresten, vad hÀnder efter att trÄden vaknar? Kommer det att fortsÀtta att utföras precis dÀr det slutade? Nej. Efter att en trÄd vaknar, dvs tiden som gÄtt som ett argument till Thread.sleep()har gÄtt, övergÄr den till körbarstat. Men detta betyder inte att trÄdschemalÀggaren kommer att köra den. Det kan mycket vÀl ge företrÀde Ät nÄgon annan icke-sovande trÄd och lÄta vÄr nyvÀckta trÄd fortsÀtta sitt arbete lite senare. Var noga med att komma ihÄg detta: att vakna betyder inte att fortsÀtta arbeta omedelbart!

Metoden Thread.join()

Multithreading: Vad metoderna i Thread-klassen gör - 4Metoden join()avbryter exekveringen av den aktuella trĂ„den tills en annan trĂ„d avslutas. Om vi ​​har 2 trĂ„dar, t1och t2, och vi skriver

t1.join()
startar sedan t2inte förrÀn t1det Àr klart. Metoden join()kan anvÀndas för att garantera exekveringsordningen för trÄdar. LÄt oss övervÀga hur join()metoden fungerar i följande exempel:

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

   }
}
Vi skapade en enkel ThreadExampleklass. Dess uppgift Ă€r att visa ett meddelande om att trĂ„den har startat, somna i 5 sekunder och sedan slutligen rapportera att arbetet Ă€r klart. LĂ€tt som en plĂ€tt. Huvudlogiken ligger i Mainklassen. Titta pĂ„ kommentarerna: vi anvĂ€nder join()metoden för att framgĂ„ngsrikt hantera trĂ„darnas exekveringsorder. Om du kommer ihĂ„g hur vi startade detta Ă€mne, hanteras exekveringsordningen av trĂ„dschemalĂ€ggaren. Den driver trĂ„dar efter eget gottfinnande: varje gĂ„ng pĂ„ ett annat sĂ€tt. HĂ€r anvĂ€nder vi metoden för att garantera att t1trĂ„den först startas och körs först, sedant2trĂ„d, och först efter det kommer programmets huvudtrĂ„d att fortsĂ€tta. GĂ„ vidare. I riktiga program hittar du ofta situationer dĂ„ du behöver avbryta exekveringen av en trĂ„d. VĂ„r trĂ„d Ă€r till exempel igĂ„ng, men den vĂ€ntar pĂ„ en viss hĂ€ndelse eller tillstĂ„nd. Om det intrĂ€ffar stannar trĂ„den. Det skulle förmodligen vara vettigt om det fanns nĂ„gon form av stop()metod. Men det Ă€r inte sĂ„ enkelt. En gĂ„ng i tiden hade Java faktiskt en Thread.stop()metod och tillĂ€t en trĂ„d att avbrytas. Men det togs senare bort frĂ„n Java-biblioteket. Du kan hitta den i Oracle-dokumentationen och se att den Ă€r markerad som utfasad. Varför? För det stoppade bara trĂ„den utan att göra nĂ„got annat. TrĂ„den kan till exempel vara att arbeta med data och Ă€ndra nĂ„got. Sedan, mitt i arbetet, avbröts den plötsligt och utan ceremonier av stop()metoden. Utan en ordentlig avstĂ€ngning, inte heller frigörande av resurser, inte ens felhantering — det fanns inget av detta. För att överdriva nĂ„got sĂ„ stop()förstörde metoden helt enkelt allt pĂ„ sitt sĂ€tt. Det var som att dra strömsladden ur uttaget för att stĂ€nga av datorn. Ja, du kan fĂ„ önskat resultat. Men alla vet att efter ett par veckor kommer datorn inte att tacka dig för att du behandlar den pĂ„ det sĂ€ttet. Det Ă€r dĂ€rför logiken för att avbryta trĂ„dar Ă€ndrades i Java och anvĂ€nder nu en speciell interrupt()metod.

Metoden Thread.interrupt()

Vad hÀnder om interrupt()metoden anropas i en trÄd? Det finns 2 möjligheter:
  1. Om objektet var i vÀntelÀge, till exempel pÄ grund av metoderna joineller sleep, avbryts vÀntan och programmet kommer att kasta en InterruptedException.
  2. Om trÄden var i ett fungerande tillstÄnd interruptedkommer den booleska flaggan att sÀttas pÄ objektet.
Men vi mÄste kontrollera vÀrdet av denna flagga pÄ objektet och slutföra arbetet korrekt pÄ egen hand! Det Àr dÀrför Threadklassen har boolean isInterrupted()metoden. LÄt oss ÄtergÄ till klockexemplet som fanns pÄ en lektion i grundkursen. För enkelhetens skull har vi förenklat det nÄgot:

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");
       }
   }
}
I det hÀr fallet startas klockan och börjar ticka varje sekund. I den 10:e sekunden avbryter vi klockans trÄd. Som du redan vet, om trÄden som vi försöker avbryta Àr i en av de vÀntande tillstÄnden, Àr resultatet en InterruptedException. Detta Àr ett kontrollerat undantag, sÄ vi kan enkelt fÄnga det och köra vÄr logik för att avsluta programmet. Och det Àr precis vad vi gjorde. HÀr Àr vÄrt resultat: Tick Tick Tick Tick Tick Tick Tick Tick Tick TrÄden avbröts Detta avslutar vÄr introduktion till Threadklassens viktigaste metoder. Lycka till!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION