JavaRush /Java-Blog /Random-DE /Multithreading: Was Thread-Klassenmethoden bewirken

Multithreading: Was Thread-Klassenmethoden bewirken

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute sprechen wir weiterhin über Multithreading. Werfen wir einen Blick auf die Thread-Klasse und die Funktionsweise ihrer verschiedenen Methoden. Früher haben wir beim Studium von Klassenmethoden meist einfach so geschrieben: „Name der Methode“ -> „was sie tut“.
Multithreading: Was die Methoden der Thread-Klasse bewirken - 1
Dies funktioniert nicht mit Thread-Methoden :) Ihre Logik ist komplizierter und ohne mehrere Beispiele unmöglich zu verstehen.

Thread.start()-Methode

Beginnen wir mit der Wiederholung. Wie Sie sich wahrscheinlich erinnern, können Sie einen Thread erstellen, indem Sie Ihre Klasse von der Klasse erben Threadund die darin enthaltene Methode überschreiben run(). Aber es wird natürlich nicht von alleine losgehen. Dazu rufen wir die Methode auf unserem Objekt auf start(). Multithreading: Was die Methoden der Thread-Klasse bewirken - 2Erinnern wir uns an das Beispiel aus der vorherigen Vorlesung:
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Выполнен поток " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Bitte beachten Sie: Um einen Thread zu starten, müssen Sie die spezielle Methode aufrufenstart(), nicht dierun()! Dieser Fehler kann leicht passieren, besonders wenn man zum ersten Mal Multithreading lernt. run()Wenn Sie in unserem Beispiel die Methode des Objekts anstelle vonaufrufenstart(), sieht das Ergebnis so aus:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Thread-0 Thread ausgeführt Thread-1 Thread ausgeführt Thread-2 Thread ausgeführt Thread-3 Thread ausgeführt Thread-4 Thread ausgeführt Thread-5 Thread ausgeführt Thread-6 Thread ausgeführt Thread-7 Thread ausgeführt Thread-8 Thread ausgeführt Thread-9 Thread ausgeführt Schauen Sie sich die Ausgabereihenfolge an: Alles läuft genau der Reihe nach ab. Seltsam, oder? Daran sind wir nicht gewöhnt, denn wir wissen bereits, dass die Reihenfolge, in der Threads gestartet und ausgeführt werden, von der Superintelligenz in unserem Betriebssystem – dem Thread-Scheduler – bestimmt wird. Vielleicht hatte ich einfach Glück? Natürlich ist es keine Frage des Glücks. Sie können dies überprüfen, indem Sie das Programm noch einige Male ausführen. Der Punkt ist, dass der direkte Aufruf einer Methoderun()nichts mit Multithreading zu tun hat. In diesem Fall wird das Programm im Hauptthread ausgeführt – demjenigen, in dem die Methode ausgeführt wirdmain(). Es werden einfach 10 Zeilen nacheinander an die Konsole ausgegeben und das war's. Es werden keine 10 Threads gestartet. Denken Sie deshalb für die Zukunft daran und überprüfen Sie sich ständig. Wenn Sie möchten, dass es erledigt wirdrun(), rufen Sie es anstart(). Lass uns weitermachen.

Thread.sleep()-Methode

Um die Ausführung des aktuellen Threads für einige Zeit anzuhalten, verwenden Sie die sleep(). Multithreading: Was die Methoden der Thread-Klasse bewirken - 3Als Parameter benötigt die Methode sleep()die Anzahl der Millisekunden, also die Zeit, die der Thread in den Ruhezustand versetzt werden muss.
public class Main {

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

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - Сколько я проспал? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " секунды");

   }
}
Konsolenausgabe: - Wie lange habe ich geschlafen? - 3 Sekunden Bitte beachten Sie: Die Methode sleep()ist statisch: Sie versetzt den aktuellen Thread in den Ruhezustand. Das heißt, diejenige, die im Moment funktioniert. Eine weitere wichtige Nuance: Der Fluss im Schlafzustand kann unterbrochen werden. In diesem Fall tritt im Programm eine Ausnahme auf InterruptedException. Nachfolgend sehen wir uns ein Beispiel an. Was passiert übrigens, nachdem der Thread „aufgewacht“ ist? Wird die Umsetzung sofort dort fortgesetzt, wo sie aufgehört hat? Nein. Nachdem der Thread aufgewacht ist – wenn die als Argument übergebene Zeit abgelaufen ist Thread.sleep()– wechselt er in den ausführbaren Zustand . Dies bedeutet jedoch nicht, dass der Thread-Scheduler ihn ausführt. Es ist gut möglich, dass es einem anderen „nicht schlafenden“ Thread den Vorzug gibt und unser „frisch erwachter“ Thread etwas später weiterarbeitet. Denken Sie unbedingt daran: „Aufwachen bedeutet nicht, in dieser Sekunde weiterzuarbeiten!“

Thread.join()-Methode

Multithreading: Was die Methoden der Thread-Klasse bewirken - 4Die Methode join()unterbricht die Ausführung des aktuellen Threads, bis ein anderer Thread abgeschlossen ist. Wenn wir 2 Threads haben t1und t2und wir schreiben -
t1.join()
t2wird erst mit der Arbeit beginnen, wenn t1 seine Arbeit abgeschlossen hat. Mit der Methode join()kann die Ausführungsreihenfolge von Threads sichergestellt werden. Schauen wir uns die Arbeit join()anhand eines Beispiels an:
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Начало работы потока " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Поток " + getName() +  " завершил работу.");
   }
}


public class Main {

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

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

       t1.start();


 /*Второй поток t2 начнет выполнение только после того, Wie будет завершен
       (oder бросит исключение) первый поток - t1*/
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       //Главный поток продолжит работу только после того, Wie t1 и t2 завершат работу
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("Все потоки закончoder работу, программа завершена");

   }
}
Wir haben eine einfache Klasse erstellt ThreadExample. Seine Aufgabe besteht darin, auf dem Bildschirm eine Meldung über den Arbeitsbeginn anzuzeigen, dann 5 Sekunden lang einzuschlafen und am Ende über den Abschluss der Arbeiten zu informieren. Nichts Kompliziertes. Die Hauptlogik ist in der Klasse enthalten Main. Schauen Sie sich die Kommentare an: Mit der Methode join()steuern wir erfolgreich die Ausführungssequenz von Threads. Wenn Sie sich an den Anfang des Themas erinnern, hat der Thread-Scheduler dies getan. Er startete sie nach eigenem Ermessen: jedes Mal anders. Hier haben wir mithilfe der Methode sichergestellt, dass zuerst der Thread gestartet und ausgeführt wird t1, dann der Thread t2und erst danach der Haupt-Thread der Programmausführung. Fortfahren. In realen Programmen werden Sie häufig auf Situationen stoßen, in denen Sie die Ausführung eines Threads unterbrechen müssen. Beispielsweise läuft unser Thread, wartet aber darauf, dass ein bestimmtes Ereignis oder eine bestimmte Bedingung erfüllt wird. Wenn das passiert, stoppt es. Es wäre wahrscheinlich logisch, wenn es eine Methode wie gäbe stop(). Allerdings ist nicht alles so einfach. Es gab einmal eine Methode Thread.stop()in Java, mit der man die Arbeit eines Threads unterbrechen konnte. Später wurde es jedoch aus der Java-Bibliothek entfernt. Sie können es in der Oracle-Dokumentation nachschlagen und sehen, dass es als veraltet markiert ist . Warum? Weil es den Fluss einfach und ohne zusätzliche Arbeit gestoppt hat. Beispielsweise könnte ein Thread mit Daten arbeiten und etwas darin ändern. stop()Dann wurde er mitten in der Arbeit plötzlich bewusstlos – und das war’s. Es gab kein ordnungsgemäßes Herunterfahren, keine Freigabe von Ressourcen, keine gleichmäßige Fehlerbehandlung – nichts davon geschah. Die Methode stop()zerstörte, um es zu übertreiben, einfach alles, was ihr in den Weg kam. Die Funktionsweise lässt sich damit vergleichen, wie jemand den Stecker aus der Steckdose zieht, um einen Computer auszuschalten. Ja, Sie können das gewünschte Ergebnis erzielen. Aber jeder versteht, dass der Computer in ein paar Wochen dafür nicht mehr „Danke“ sagen wird. Aus diesem Grund wurde die Logik zum Unterbrechen von Threads in Java geändert und jetzt wird eine spezielle Methode verwendet – interrupt().

Thread.interrupt()-Methode

Was passiert, wenn Sie eine Methode für einen Thread aufrufen interrupt()? Es gibt 2 Möglichkeiten:
  1. Befand sich das Objekt zu diesem Zeitpunkt beispielsweise im Wartezustand joinoder sleep, wird das Warten unterbrochen und das Programm löst aus InterruptedException.
  2. Wenn sich der Thread zu diesem Zeitpunkt in einem Arbeitszustand befand, wird das boolesche Flag des Objekts gesetzt interrupted.
Aber wir müssen das Objekt auf den Wert dieser Flagge prüfen und die Arbeit selbst korrekt abschließen! Zu diesem Zweck verfügt die Klasse Threadüber eine spezielle Methode – boolean isInterrupted(). Kehren wir noch einmal zum Uhrenbeispiel aus der Hauptvorlesung zurück. Der Einfachheit halber ist es etwas vereinfacht:
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("Работа потока была прервана");
               break;
           }
           System.out.println("Tik");
       }
   }
}
In unserem Fall startet und beginnt die Uhr jede Sekunde zu ticken. Bei der 10. Sekunde unterbrechen wir den Taktfluss. Wie Sie bereits wissen, führt dies zu , wenn sich der Thread, den wir zu unterbrechen versuchen, in einem der Wartezustände befindet InterruptedException. Diese Art von Ausnahme ist eine geprüfte Ausnahme, sodass sie leicht abgefangen und unsere Programmbeendigungslogik ausgeführt werden kann. Das haben wir getan. Hier ist unser Ergebnis: Tik Tik Tik Tik Tik Tik Tik Tik Tik Die Arbeit des Threads wurde unterbrochen. Damit ist unsere Einführung in die Hauptmethoden der Klasse abgeschlossen Thread. Um Ihr Wissen zu festigen, können Sie sich diesen Videovortrag zum Thema Multithreading ansehen:
Es wird als hervorragendes Zusatzmaterial dienen! Am Ende, nach einem Überblick über die Methoden, erfahren Sie genau, was wir im weiteren Verlauf des Kurses durchgehen werden :) Viel Glück!
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION