Ich stöbere oft auf. In Bezug auf die Benachrichtigung und Benachrichtigung in Java haben Menschen häufig die folgenden Aussagen:
Benachrichtigung benachrichtigt nur ein Objekt wartet, während Notifyall alle Objekte wartet, und alle Objekte werden weiter ausgeführt.
Und es scheint, dass es Beispiele gibt, die es beweisen. Die obige Erklärung kann als korrekt sein oder nicht. Der Grund ist, dass einer von ihnen sehr wichtig ist. Die offizielle Erklärung lautet wie folgt:
Warten Sie, benachrichtigen, benachrichtigen Sie:
Diese Methode sollte nur von einem Thread aufgerufen werden, der der Eigentümer dieses Objektmonitors ist. Ein Thread kann auf eine von drei Arten Eigentümer dieses Objektmonitors werden:
Durch Ausführung der Synchroninstanzmethode dieses Objekts.
Der Körper der synchronisierten Anweisung wird ausgeführt, indem die synchronisierte Anweisung zu diesem Objekt ausgeführt wird.
Für Objekte der Typ -Klasse können Sie synchrone statische Methoden der Klasse ausführen.
Nur ein Thread verfügt über einen Objektmonitor gleichzeitig.
Die obige Aussage wird aus Javadoc ausgerichtet. Dies bedeutet, dass im Anruf der Objektmonitor (d. H. Sperre) gehalten werden muss, was wir verstehen können, wenn wir innerhalb der synchronisierten Methode ausgeführt werden. Die implizite Bedeutung dieser Aussage lautet: Wenn Sie den im Synchronisationsblock enthaltenen Codeblock fortsetzen möchten, müssen Sie das Schloss wieder aufnehmen. Dieser Satz ist in Javadoc beschrieben:
Warten
Diese Methode bewirkt, dass sich der aktuelle Thread (als T) in die Warteschleife des Objekts einfügt und dann alle Synchronisationsanforderungen für dieses Objekt aufgibt. Für Thread -Planungszwecke ist Thread T deaktiviert und ist im Winterschlaf, bevor eine der folgenden vier Situationen auftritt:
Einige andere Threads rufen die Benachrichtigungsmethode dieses Objekts auf, und Thread t wird zufällig als Weckenthread ausgewählt.
Einige andere Threads rufen die Notifyall -Methode dieses Objekts auf.
Einige andere Threads unterbrechen Thread T.
Ungefähr die angegebene tatsächliche Zeit wurde erreicht. Wenn die Zeitüberschreitung jedoch Null ist, wird die tatsächliche Zeit nicht berücksichtigt und der Thread wartet, bis die Benachrichtigung erhalten wird.
Dann wird Thread T aus dem Wartesatz des Objekts gelöscht und die Thread -Planung wird erneut durchgeführt. Der Thread konkurriert dann mit anderen Threads auf herkömmliche Weise, um das Recht zu erhalten, das Objekt zu synchronisieren. Sobald die Kontrolle über das Objekt erhalten ist
Die Situation, wenn die Methode ist. Thread T kehrt dann vom Anruf zur Warteverfahren zurück. Bei der Rückkehr aus der Wartenmethode ist der Synchronisationszustand des Objekts und des Thread T genau das gleiche wie beim Aufrufen der Wartenmethode.
Das heißt, das Schloss muss erneut betroffen sein, damit alle Threads zur Benachrichtigung benachrichtigt wurden. Diese Threads werden jedoch konkurrieren, und nur ein Thread erfasst das Schloss erfolgreich. Bevor dieser Thread ausgeführt wird, müssen andere Threads warten (aber es besteht keine Notwendigkeit, die Benachrichtigung hier zu benachrichtigen, da sie benachrichtigt werden, und es ist nur erforderlich, das Schloss zu erwerben). Es gibt den folgenden Code, der dieses Phänomen reproduzieren kann.
Definieren Sie zunächst eine Thread -Klasse, die wie folgt ausgeführt werden kann:
privates statisches endgültiges Objekt obj = neues Objekt (); statische Klasse R implementiert Runnable {int i; R (int i) {this.i = i; } public void run () {try {synchronized (obj) {system.out.println ("thread->" + i + "wartet"); obj.wawait (); System.out.println ("Thread->" + i + "running"); Thread.Sleep (30000); }} catch (Ausnahme e) {e.printstacktrace (); }}} Achten Sie auf die Innenseite der oben genannten Run -Methode. Nach dem Warten () drucken wir einen Satz und pausieren dann den aktuellen Code für 30 Sekunden. In Bezug auf die Schlafmethode wird sie wie folgt beschrieben:
Der Thread verliert kein Eigentum an Monitoren.
Das heißt, das Schloss wird noch abgehalten.
Definieren Sie dann eine Hauptmethode, um diese Threads wie folgt auszuführen:
Thread [] rs = neuer Thread [10]; für (int i = 0; i <10; i ++) {rs [i] = neuer Thread (neuer r (i)); } für (Thread R: rs) {R.Start (); } Thread.sleep (5000); synchronisiert (obj) {obj.notifyallAll (); }Wir definieren 10 Threads und führen sie dann alle aus. Da es warten, warten 10 Threads nach dem Ausdruck "Start Run". Dann die Hauptmethode aufrufe notifyAll. Die Ausgabe hier wird wie folgt angezeigt:
Thread-> 0 Warten auf Thread-> 4 Warten auf Thread-> 5 Warten auf Thread-> 3 Warten auf Thread-> 2 Warten auf Thread-> 1 Warten auf Thread-> 6 Warten auf Thread-> 7 Warten auf Thread-> 8 Warten auf Thread-> 9 Warten auf Thread-> 9 Laufen
... keine andere Ausgabe innerhalb von 30 Sekunden
In der obigen Ausgabe gibt nach dem Warten nur ein Thread die Anweisung "Running" aus, und für einen bestimmten Zeitraum (30 Sekunden hier) gibt es keine andere Ausgabe. Das heißt, andere Threads geben nicht zwischen den vom aktuellen Code gehaltenen Sperren aus.
Die endgültige Schlussfolgerung lautet: Wenn der wartende Thread weiter laufen will, muss er zwei Bedingungen erfüllen:
Der andere Thread benachrichtigt oder benachrichtigt wurde benachrichtigt und der aktuelle Thread wurde benachrichtigt.
Nach dem Wettbewerb mit anderen Fäden zum Sperren wurden zwei Bedingungen erfolgreich für das Verschließen erhalten, und keiner von ihnen fehlte. Tatsächlich erzielen Sie auf der Implementierungsebene den gleichen Effekt, und ein Thread wird weiterhin ausgeführt. Aber es ist befreit. Die Notwendigkeit, andere Threads nach dem Ausführen des Threads zu benachrichtigen, da er benachrichtigt wurde. Wenn Sie Benachrichtigung verwenden und Benachrichtigung verwenden müssen, hängt dies von der tatsächlichen Situation ab.
Das obige ist eine Zusammenstellung der Informationen für Java Benachrichtigung und Benachrichtigung. Wir werden in Zukunft weiterhin relevante Informationen hinzufügen. Vielen Dank für Ihre Unterstützung für diese Website!