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