Hallo! Heute sprechen wir weiter über Multithreading. Sehen wir uns die Thread-Klasse und die Funktionsweise einiger ihrer Methoden an. Wenn wir früher Klassenmethoden untersucht haben, haben wir normalerweise einfach Folgendes geschrieben: <Methodenname> -> <was die Methode tut>.
Mit den Methoden von wird das nicht funktionieren
Erinnern wir uns an das Beispiel aus der vorherigen Lektion:
Die
Die

Thread
:) Sie verfügen über eine komplexere Logik, die Sie ohne ein paar Beispiele nicht verstehen können.
Die Thread.start()-Methode
Beginnen wir damit, uns zu wiederholen. Wie Sie sich wahrscheinlich erinnern, können Sie einen Thread erstellen, indem Sie Ihre Klasse veranlassen, dieThread
Klasse zu erben und die run()
Methode zu überschreiben. Aber es startet natürlich nicht von selbst. Dazu rufen wir start()
die Methode unseres Objekts auf. 
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();
}
}
}
Hinweis:start()
Um einen Thread zu starten, müssen Sie die spezielle Methode und nicht dierun()
MethodeaufrufenDies ist ein leicht zu begehender Fehler, insbesondere wenn Sie sich zum ersten Mal mit Multithreading beschäftigen. Wenn Sie in unserem Beispiel dierun()
Methode zehnmal anstelle vonstart()
, erhalten Sie Folgendes:
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.run();
}
}
}
Sehen Sie sich die Ergebnisse unseres Programms an: Thread ausgeführt: 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 Schauen Sie sich die Reihenfolge der Ausgabe an: Alles geschieht in perfekter Reihenfolge. Seltsam, oder? Wir sind daran nicht gewöhnt, weil wir bereits wissen, dass die Reihenfolge, in der Threads gestartet und ausgeführt werden, von einem übergeordneten Intellekt in unserem Betriebssystem bestimmt wird: dem Thread-Scheduler. Vielleicht hatten wir einfach Glück? Dabei geht es natürlich nicht um Glück. Sie können dies überprüfen, indem Sie das Programm noch einige Male ausführen. Das Problem ist, dass der Anruf erfolgtrun()
Methode hat direkt nichts mit Multithreading zu tun. In diesem Fall wird das Programm im Hauptthread ausgeführt, dem gleichen Thread, der die main()
Methode ausführt. Es werden einfach nacheinander 10 Zeilen auf der Konsole ausgegeben und fertig. 10 Threads wurden nicht gestartet. Denken Sie also in Zukunft daran und überprüfen Sie sich ständig. Wenn Sie möchten, dass die run()
Methode aufgerufen wird, rufen Sie auf start()
. Gehen wir weiter.
Die Thread.sleep()-Methode
Um die Ausführung des aktuellen Threads für eine Weile anzuhalten, verwenden wir diesleep()
Methode. 
sleep()
Methode benötigt eine Anzahl von Millisekunden als Argument, die angibt, wie lange es dauert, den Thread in den Ruhezustand zu versetzen.
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");
}
}
Konsolenausgabe:
- Wie lange habe ich geschlafen?
- 3 Sekunden
Hinweis: Die sleep()
Methode ist statisch: Sie schläft den aktuellen Thread. Das heißt, derjenige, der gerade ausgeführt wird. Hier noch ein wichtiger Punkt: Ein schlafender Thread kann unterbrochen werden. In diesem Fall wirft das Programm eine InterruptedException
. Nachfolgend betrachten wir ein Beispiel. Was passiert übrigens, nachdem der Thread aufgewacht ist? Wird die Ausführung dort fortgesetzt, wo sie aufgehört hat? Nein. Nachdem ein Thread aufgewacht ist, dh die als Argument übergebene Zeit abgelaufen ist Thread.sleep()
, geht er in den ausführbaren Zustand überZustand. Dies bedeutet jedoch nicht, dass der Thread-Scheduler es ausführt. Möglicherweise gibt es einem anderen nicht schlafenden Thread den Vorzug und ermöglicht unserem frisch erwachten Thread, seine Arbeit etwas später fortzusetzen. Denken Sie unbedingt daran: Aufwachen bedeutet nicht, sofort mit der Arbeit fortzufahren!
Die Thread.join()-Methode

join()
Methode unterbricht die Ausführung des aktuellen Threads, bis ein anderer Thread beendet ist. Wenn wir 2 Threads haben t1
und t2
und wir schreiben
t1.join()
t2
startet dann erst, wenn t1
seine Arbeit beendet ist. Die join()
Methode kann verwendet werden, um die Ausführungsreihenfolge von Threads zu garantieren. Betrachten wir die join()
Funktionsweise der Methode im folgenden Beispiel:
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.");
}
}
Wir haben eine einfache ThreadExample
Klasse erstellt. Seine Aufgabe besteht darin, eine Meldung anzuzeigen, dass der Thread gestartet wurde, 5 Sekunden lang einzuschlafen und schließlich zu melden, dass die Arbeit abgeschlossen ist. Stück Kuchen. Die Hauptlogik liegt in der Main
Klasse. Schauen Sie sich die Kommentare an: Wir verwenden die join()
Methode, um die Ausführungsreihenfolge der Threads erfolgreich zu verwalten. Wenn Sie sich erinnern, wie wir mit diesem Thema begonnen haben, wird die Ausführungsreihenfolge vom Thread-Scheduler verwaltet. Es führt Threads nach eigenem Ermessen aus: jedes Mal auf eine andere Art und Weise. Hier verwenden wir die Methode, um sicherzustellen, dass t1
zuerst der Thread gestartet und ausgeführt wird, dann dert2
Thread, und erst danach wird der Hauptthread des Programms fortgesetzt. Weiter geht's. In realen Programmen kommt es oft vor, dass Sie die Ausführung eines Threads unterbrechen müssen. Beispielsweise läuft unser Thread, wartet aber auf ein bestimmtes Ereignis oder eine bestimmte Bedingung. Wenn es auftritt, stoppt der Thread. Es wäre wahrscheinlich sinnvoll, wenn es eine stop()
Methode gäbe. Aber es ist nicht so einfach. Es war einmal, dass Java tatsächlich eine Thread.stop()
Methode hatte und die Unterbrechung eines Threads ermöglichte. Später wurde es jedoch aus der Java-Bibliothek entfernt. Sie können es in der Oracle-Dokumentation finden und sehen, dass es als veraltet markiert ist. Warum? Weil es den Thread einfach gestoppt hat, ohne etwas anderes zu tun. Beispielsweise könnte der Thread mit Daten arbeiten und etwas ändern. Dann wurde es mitten in seiner Arbeit abrupt und kurzerhand durch die stop()
Methode abgebrochen. Ohne ordnungsgemäßes Herunterfahren, ohne die Freigabe von Ressourcen, ohne Fehlerbehandlung – all das gab es nicht. Um es leicht zu übertreiben: Die stop()
Methode zerstörte einfach alles, was ihr in den Weg kam. Es war, als würde man das Netzkabel aus der Steckdose ziehen, um den Computer auszuschalten. Ja, Sie können das gewünschte Ergebnis erzielen. Aber jeder weiß, dass der Computer es Ihnen nach ein paar Wochen nicht mehr danken wird, dass Sie ihn so behandeln. Aus diesem Grund hat sich in Java die Logik zum Unterbrechen von Threads geändert und verwendet nun eine spezielle interrupt()
Methode.
Die Thread.interrupt()-Methode
Was passiert, wenn dieinterrupt()
Methode in einem Thread aufgerufen wird? Es gibt 2 Möglichkeiten:
join
Wenn sich das Objekt beispielsweise aufgrund der oder- Methoden im Wartezustand befandsleep
, wird das Warten unterbrochen und das Programm löst eine ausInterruptedException
.- Wenn sich der Thread in einem funktionierenden Zustand befand,
interrupted
wird das boolesche Flag für das Objekt gesetzt.
Thread
hat die Klasse die boolean isInterrupted()
Methode. Kehren wir zum Uhrenbeispiel aus einer Lektion im Grundkurs zurück. Der Einfachheit halber haben wir 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("The thread was interrupted");
break;
}
System.out.println("Tick");
}
}
}
In diesem Fall wird die Uhr gestartet und beginnt im Sekundentakt zu ticken. In der 10. Sekunde unterbrechen wir den Takt der Uhr. Wie Sie bereits wissen, ist das Ergebnis ein , wenn sich der Thread, den wir zu unterbrechen versuchen, in einem der Wartezustände befindet InterruptedException
. Dies ist eine geprüfte Ausnahme, sodass wir sie leicht abfangen und unsere Logik ausführen können, um das Programm zu beenden. Und genau das haben wir getan.
Hier ist unser Ergebnis:
Tick
Tick
Tick
Tcik
Tick
Tick
Tick
Tick
Tick
Der Thread wurde unterbrochen.
Damit ist unsere Einführung in die Thread
wichtigsten Methoden der Klasse abgeschlossen. Viel Glück!
GO TO FULL VERSION