In diesem Kapitel werden wir die Thread-Warte-/Weckmethode vorstellen. Der betreffende Inhalt umfasst:
1. Einführung in Wait (), Notify (), Notifyall () und andere Methoden
2. Wait () und benachrichtigen ()
3. Warten Sie (langfristig) und benachrichtigen Sie ()
4. Wait () und notifyAll ()
5. Warum werden Benachrichtigung (), Wait () und andere im Objekt definierte Funktionen, nicht Thread
Einführung in Wait (), Notify (), Notifyall () und andere Methoden
In Object.java werden Schnittstellen wie Wait (), benachrichtigen () und Notifyall () definiert. Die Funktion von Wait () besteht darin, den aktuellen Thread in einen Wartezustand einzugeben, und Wait () lässt den aktuellen Thread auch das von ihm gehaltene Sperre loslassen. Die Rolle von Notify () und NotifyAll () besteht darin, den wartenden Thread auf dem aktuellen Objekt aufzuwecken.
Die API -Details zum Warten/Wachen in der Objektklasse sind wie folgt:
Benachrichtigen () - Wachen Sie einen einzelnen Thread auf, der auf diesen Objektmonitor wartet.
NotifyAll () - Weck alle Threads auf, die auf diesen Objektmonitor wartet.
Wait () - Stecken Sie den aktuellen Thread in eine "Warte (Blocking) -Schate" und "bis andere Threads die montify () -Methode oder notifyall () dieses Objekts aufrufen" und der aktuelle Thread wird erweckt (eingegeben in die "eingegeben" Bereites Zustand ").
Warten Sie (langfristig) - Lassen Sie den aktuellen Thread in einem "Warten- (Blockierungs-) Zustand" und "bis andere Threads die melden () -Methode aufrufen oder die montifyAll () dieses Objekts aufrufen oder die angegebene Zeitmenge überschreiten", und der aktuelle Thread wird geweckt (geben Sie "Ready" ein).
Warten Sie (langfristig, int nanos) - Stecken Sie den aktuellen Thread in einen "Warten- (Blockier-) Status", bis ein anderer Thread die Methode benachrichtigen () oder notifyAll () dieses Objekts aufruft, oder ein anderer Thread unterbricht den aktuellen Thread. oder die tatsächliche Zeit ist überschritten "und der aktuelle Thread wird erweckt (in" Ready State "eingegeben).
2. Beispiele warten () und notify ()
Das Folgende ist ein Beispiel, um "Wait () und benachrichtigen () zusammen zu demonstrieren.
Die Codekopie lautet wie folgt:
// WaitTest.java Quellcode
Klasse Threada erweitert Thread {
public threada (String name) {
Super (Name);
}
public void run () {
synchronisiert (this) {
System.out.println (Thread.currentThread (). GetName ()+"call benociify ()");
// Wach den aktuellen Wartewart Thread auf
benachrichtigen();
}
}
}
public class waitTest {
public static void main (String [] args) {
Threada t1 = neuer Threada ("T1");
synchronisiert (t1) {
versuchen {
// Start "Thread T1"
System.out.println (Thread.currentThread (). GetName ()+"start t1");
t1.start ();
// Der Haupt -Thread wartet darauf, dass T1 aufwacht.
System.out.println (Thread.currentThread (). GetName ()+"wait ()");
t1.wait ();
System.out.println (Thread.currentThread (). GetName ()+"Fortsetzung");
} catch (InterruptedException e) {
E. printstacktrace ();
}
}
}
}
Auslaufergebnisse:
Die Codekopie lautet wie folgt:
Hauptstart T1
Hauptwart ()
t1 call musify ()
Haupt weiter
Ergebnisse Beschreibung:
Die folgende Abbildung zeigt den Fluss von "Hauptfaden" und "Thread T1".
(01) Beachten Sie, dass der "Hauptfaden" in der Abbildung "Hauptfaden Haupt" darstellt. "Thread T1" repräsentiert "Thread T1" in Wartest. Und "Lock" repräsentiert "Synchronen des Objekts T1".
(02) "Haupt Thread" erstellt einen neuen "Thread T1" über New Threada ("T1"). Dann wird die "synchrone Schloss des T1 -Objekts" durch synchronisiert (T1) erhalten. Rufen Sie dann t1.start () an, um "Thread T1" zu starten.
(03) "Haupt Thread" führt t1.wait () aus, um "Lock of T1 -Objekt" zu veröffentlichen und in den Status "Waiting (Blocking)" zu gelangen. Warten Sie, bis Threads zu T1 -Objekten über Notify () oder NotifyAll () aufweckt werden.
(04) Nachdem "Thread T1" ausgeführt wurde, wird die "Sperre des aktuellen Objekts" durch synchronisiert (dies) erhalten. der "Hauptfaden".
(05) Veröffentlichen Sie nach Abschluss "Thread T1" die "Sperre des aktuellen Objekts". Unmittelbar danach erwirbt der "Hauptfaden" das "Schloss des T1 -Objekts" und wird dann ausgeführt.
Für den obigen Code? Ein Freund fragte einmal: T1.wait () sollte "Thread T1" warten lassen;
Schauen wir uns vor der Beantwortung dieser Frage einen Absatz über Warte im JDK -Dokument an:
Die Codekopie lautet wie folgt:
Bewirkt, dass der aktuelle Thread wartet, bis ein anderer Thread die montify () -Methode oder die meldenAll () -Methode für dieses Objekt aufruft.
Mit anderen Worten, diese Methode verhält sich genau so, als würde sie einfach den Anruf warten (0).
Der aktuelle Thread muss den Monitor dieses Objekts besitzen. Kann das Eigentum des Monitors wieder beobachten und die Ausführung fortsetzt.
Die Bedeutung auf Chinesisch ist ungefähr:
Bewirkt, dass der "aktuelle Thread" wartet, bis ein anderer Thread -Aufruf () oder notifyAll () den Thread weckt. Mit anderen Worten, diese Methode hat den gleichen Effekt wie das Warten (0)! (Ergänzend, für die Wartezeit (lange Millis) Methode, wenn Millis 0 ist, bedeutet dies, dass unendlich wartet, bis sie von melden () oder notifyall ()) geweckt wird.
Wenn der "aktuelle Thread" aufgerufen wird (), muss die Synchronisationsschloss für das Objekt enthalten sein. Nachdem der Thread -Anruf () () das Schloss freigegeben wird. Der Thread wartet dann weiter, bis er das "Synchronisierungsschloss für dieses Objekt" rekonjiziert und dann weiter ausgeführt wird.
Hinweis: In der Erklärung von JDK wird gesagt, dass die Funktion von Wait () darin besteht, den "aktuellen Thread" zu warten, und der "aktuelle Thread" bezieht sich auf den Thread, der auf der CPU ausgeführt wird!
Dies bedeutet auch, dass zwar t1.wait () die Wait () -Methode ist, die durch "Thread T1" genannt wird, der Ort, an dem T1.wait () aufgerufen wird, in "Hauptfaden -Haupt" ist. Der Haupt -Thread muss der "aktuelle Thread" sein, dh der laufende Status, bevor t1.wait () ausgeführt werden kann. Daher ist der "aktuelle Thread" zu diesem Zeitpunkt die "Haupt -Thread -Main"! Daher ist T1.wait (), den "Haupt -Thread" zu warten, nicht "Thread T1"!
3. Warten Sie (langfristig) und benachrichtigen Sie ()
Warten Sie (langfristig). Legen Sie den aktuellen Thread in eine "Warten- (Blockierungs-) Status" und "bis andere Threads die Methode benachrichtigen () oder notifyAll () dieses Objekts aufrufen oder die angegebene Zeitspanne und die Zeit überschreiten" und die Der aktuelle Thread wird geweckt (eingegeben) "bereit").
Das folgende Beispiel zeigt das wartende (langfristige) Zeitübergang und der Thread wird erweckt.
Die Codekopie lautet wie folgt:
// Quellcode von WaittimeoutTest.java
Klasse Threada erweitert Thread {
public threada (String name) {
Super (Name);
}
public void run () {
System.out.println (Thread.currentThread (). GetName () + "run");
// ein Teufelskreis, ständig laufen.
Während (wahr)
}
}
public class WaitTimeoutTest {
public static void main (String [] args) {
Threada t1 = neuer Threada ("T1");
synchronisiert (t1) {
versuchen {
// Start "Thread T1"
System.out.println (Thread.currentThread (). GetName () + "start t1");
t1.start ();
// Der Haupt -Thread wartet darauf, dass T1 durch Benachrichtigung () oder NotifyAll () oder Verzögerungen von mehr als 3000 ms aufwacht.
System.out.println (Thread.currentThread (). GetName () + "call wait");
t1.wait (3000);
System.out.println (Thread.currentThread (). GetName () + "Fortsetzung");
} catch (InterruptedException e) {
E. printstacktrace ();
}
}
}
}
Auslaufergebnisse:
Die Codekopie lautet wie folgt:
Hauptstart T1
Hauptanruf warten
T1 Run // nach ca. 3 Sekunden ... Ausgabe "Main Weiter" "
Haupt weiter
Ergebnisse Beschreibung:
Die folgende Abbildung zeigt den Fluss von "Hauptfaden" und "Thread T1".
(01) Beachten Sie, dass der "Hauptgewinde" in der Abbildung den WaitTimeouttest -Haupt -Thread (d. H. Thread Main) darstellt. "Thread T1" repräsentiert Thread T1 in WaitTest. Und "Lock" repräsentiert "Synchronen des Objekts T1".
(02) Der Haupt -Thread -Haupt -Haupt -Main führt t1.start () aus, um "Thread T1" zu starten.
(03) Der Haupt -Thread -Main führt t1.wait (3000) aus, und zu diesem Zeitpunkt tritt der Haupt -Thread in den "Blockierstatus" ein. Es ist notwendig, "den Faden, der für die T1 -Objektsperrung verwendet wird, um sie durch Notify () oder NotifyAll ()" oder "After 3000 ms Timeout" aufzuwecken, in die Hauptfaden -Haupt -Hauptstatus tritt in den "Ready State" ein und kann dann ausgeführt werden.
(04) Nachdem "Thread T1" ausgeführt wird, geht es in eine tote Schleife ein und läuft weiter.
(05) Nachdem das Timeout 3000 ms beträgt, tritt der Haupt -Thread -Main in den "Ready State" ein und dann in den "Laufstatus".
4. Wait () und notifyAll ()
Durch das vorherige Beispiel wissen wir, dass Benachrichtigung () einen einzelnen Thread auf diesen Objektmonitor aufwachen kann.
Im Folgenden demonstrieren wir die Verwendung von Notifyall () durch ein Beispiel;
Die Codekopie lautet wie folgt:
öffentliche Klasse notifyAllTest {
privates statisches Objekt obj = neues Objekt ();
public static void main (String [] args) {
Threada t1 = neuer Threada ("T1");
Threada t2 = new threada ("t2");
Threada t3 = new threada ("t3");
t1.start ();
t2.Start ();
t3.Start ();
versuchen {
System.out.println (Thread.currentThread (). GetName ()+"schlaf (3000)");
Thread.sleep (3000);
} catch (InterruptedException e) {
E. printstacktrace ();
}
synchronisiert (obj) {
// Der Hauptfaden wartet auf das Aufwachen.
System.out.println (Thread.currentThread (). GetName ()+"notifyAll ()");
obj.notifyall ();
}
}
Statische Klasse Threada erweitert Thread {
public threada (String name) {
Super (Name);
}
public void run () {
synchronisiert (obj) {
versuchen {
// Ausgabeergebnis drucken
System.out.println (Thread.currentThread (). GetName () + "Wait");
// Wach den aktuellen Wartewart Thread auf
obj.wawait ();
// Ausgabeergebnis drucken
System.out.println (Thread.currentThread (). GetName () + "Fortsetzung");
} catch (InterruptedException e) {
E. printstacktrace ();
}
}
}
}
}
Auslaufergebnisse:
Die Codekopie lautet wie folgt:
t1 warte
Hauptschlaf (3000)
T3 warte
T2 warte
Hauptbenachrichtigung ()
T2 Weiter
T3 weiter
t1 weiter
Ergebnisse Beschreibung:
Weitere Informationen finden Sie im folgenden Flussdiagramm.
(01) 3 Threads "T1", "T2" und "T3" wurden erstellt und im Hauptfaden begonnen.
(02) Der Hauptfaden schläft 3 Sekunden im Schlaf (3000). Während des Hauptfadenschlafes für 3 Sekunden gehen wir davon aus, dass die drei Fäden "T1", "T2" und "T3" alle laufen. Nehmen wir als Beispiel "T1". Warten Sie auch darauf, dass andere Themen sie durch nofity () oder nofityAll () aufwecken.
(03) Der Hauptfaden schläft 3 Sekunden lang und läuft dann. Führen Sie obj.notifyall () aus, um den wartenden Thread auf OBJ aufzuwecken, dh die drei Threads "T1", "T2" und "T3" aufzuwecken. Unmittelbar nach dem Ausführen des Hauptfadens synchronisiert (OBJ) setzt der Hauptfaden das "OBJ Lock" frei. Auf diese Weise können "T1", "T2" und "T3" das "OBJ Lock" erhalten und weiter laufen!
5. Warum werden Benachrichtigung (), Wait () und andere im Objekt definierte Funktionen, nicht Thread
Funktionen wie Wait (), benachrichtigen () im Objekt wie synchronisiert werden die "Objektsynchronisationsschloss" betrieben.
Wait () lässt den "aktuellen Thread" warten. nicht in der Lage sein zu rennen!
OK, nachdem der Thread -Aufrufe warten () wird das "Synchronen Schloss" von seiner Schloss veröffentlichen. Nach der vorherigen Einführung wissen wir, dass der wartende Thread von notify () oder notifyAll () geweckt werden kann. Denken Sie nun bitte über eine Frage nach: Was wird auf der Grundlage des erwarteten Threads benachrichtigt ()? Oder wie hoch ist die Korrelation zwischen Wait () und Notify ()? Die Antwort lautet: Basierend auf "Objektsynchronisationsschloss".
Der Thread, der für das Aufwachen des wartenden Threads verantwortlich ist (wir nennen es "Wake up Thread"), erwerbt nur die "Synchronisierungsschloss des Objekts" (die Synchronisationsschloss hier muss mit der Synchronisationsschloss des wartenden Threads übereinstimmen). und Anrufe benachrichtigen () oder nach der musifigall () -Methode kann der wartende Thread erweckt werden. Obwohl der wartende Thread erweckt wird; Sie müssen warten, bis der Wakup-Thread das "Synchronisationsschloss des Objekts" freigibt, bevor Sie das "Synchronisationsschloss des Objekts" erhalten und weiter ausgeführt werden können.
Kurz gesagt, benachrichtigen (), Wait () stützt sich auf "Synchronen Schloss", das von Objektschlössern gehalten wird, und jedes Objekt hat und nur eines! Aus diesem Grund werden Funktionen wie Notify (), Wait () in der Objektklasse definiert, nicht in der Thread -Klasse.