Countdownlatch ist eine nützliche Werkzeugklasse. Mit der Verwendung können wir ein oder mehrere Threads abfangen, um nach einem bestimmten Zustand reif zu werden. Der interne Inhalt liefert einen Zähler, und der Anfangswert des Zählers muss beim Erstellen einer Sperre angegeben werden, und der Anfangswert des Zählers muss größer als 0 sein. Darüber hinaus bietet er auch eine Countdown -Methode zum Betrieb des Zählerwerts. Der Zähler wird jedes Mal, wenn die Countdown -Methode aufgerufen wird, um 1 verringert. Wenn der Zählerwert auf 0 reduziert wird, bedeutet dies, dass die Bedingungen reif sind und alle Threads, die durch Aufrufen der wartenden Methode blockiert werden, geweckt werden. Dies ist der interne Mechanismus des Countdownlatch. Es sieht sehr einfach aus, es ist nichts anderes, als einige Threads zu blockieren und ihnen nach Erreichen eines bestimmten Zustands auszuführen. Countdownlatch verfügt jedoch über eine Vielzahl von Anwendungsszenarien. Solange Sie einen großen Verstand haben und es benutzen, können Sie verschiedene Tricks spielen. Das häufigste Anwendungsszenario besteht darin, mehrere Threads gleichzeitig auszuführen und dann die Ergebnisse zu zählen und zusammenzufassen, nachdem alle Aufgaben ausgeführt wurden. Die folgende Abbildung zeigt dynamisch den gesamten Prozess des Blockierens von Threads.
Die obige Abbildung zeigt, dass 5 Threads blockiert werden, indem die Warteverfahren aufgerufen wird, und sie müssen warten, bis der Zählerwert auf 0 abnimmt, bevor sie weiter ausgeführt werden. Der Anfangswert des Zählers wird bei der Erstellung einer Sperre angegeben und anschließend mit jedem Aufruf auf die Countdown -Methode um 1 reduziert. Der folgende Code veröffentlicht die Countdownlatch -Konstruktionsmethode.
// Constructor Public Countdownlatch (int count) {if (count <0) neue illegalArgumentException ("count <0"); this.ync = new Sync (count); }Countdownlatch hat nur einen Parameterkonstruktor, und ein Wert von mehr als 0 muss als Anfangswert des Zählers übergeben werden, andernfalls wird ein Fehler gemeldet. Sie können sehen, dass im Konstruktor nur ein neuer Synchronisationsobjekt und die Mitgliedsynchronisierungssynchronisation zugewiesen wird. Wie bei anderen Synchronisierungs -Toolklassen stützt sich die Implementierung von Countdownlatch auf AQs, eine Anwendung im AQS Shared -Modus. Countdownlatch implementiert eine interne Klassensynchronisierung und verwendet sie zum Erben von AQs, so dass die meisten von AQs bereitgestellten Methoden verwendet werden können. Schauen wir uns den Code der internen Synchronisation an.
// Synchronizer private statische endgültige Klasse Sync erweitert AbstractQueuedsynchronizer {// Konstruktorsynchronisierung (int count) {setState (count); } // den aktuellen Synchronisierungszustand int -GetCount () {return getState () erhalten; } // Versuchen Sie, die Sperre zu erhalten // Negative Zahl zurückgeben: Zeigt an, dass der aktuelle Thread nicht erhalten wurde // Nullwert zurückgeben: Gibt an, dass der aktuelle Thread erfolgreich erfasst wurde, aber der nachfolgende Thread kann nicht mehr eine positive Zahl zurückgeben. 1: -1; } // Versuchen Sie, den sperig geschützten booleschen tryreleaseshared (int resurees) {for (;;) {// den Synchronisationszustand int c = getState () abrufen; // Wenn der Synchronisationszustand 0 ist, if (c == 0) {return false; } // Ansonsten reduzieren Sie den Synchronisationszustand durch 1 int nextc = c-1; // Verwenden Sie die CAS -Methode, um den Synchronisationszustand zu aktualisieren, wenn (vergleicheStSetState (c, nextc)) {return nextc == 0; }}}}Sie können sehen, dass der Konstruktor von Sync den Wert des Synchronisationszustands auf den übergebenen Parameterwert festlegt. Danach wird jedes Mal, wenn die Countdown -Methode aufgerufen wird, der Wert des synchronen Zustands um 1 reduziert, was das Implementierungsprinzip des Zählers ist. Die beiden am häufigsten verwendeten Methoden bei der Verwendung der Countdownlatch -Toolklasse sind die Warte -Methode und die Countdown -Methode. Das Aufrufen der Warte -Methode blockiert den aktuellen Thread, bis der Zähler 0 ist, und das Aufrufen der Countdown -Methode verringert den Zählerwert um 1, bis er auf 0 reduziert wird. Schauen wir uns an, wie die Warte -Methode aufgerufen wird.
// lässt den aktuellen Thread warten, bis die Verriegelung auf 0 abnimmt, oder der Thread wird unterbrochen. Ausnahme if (thread.interrupted ()) {throw New InterruptedException (); } // 1. Versuchen Sie, das Schloss zu erwerben, wenn (tryacquireshared (arg) <0) {// 2. Wenn die Akquisition fehlschlägt, geben Sie die Methode doacquiresharedinterriptable (ARG) ein. }}Wenn der Thread die wartende Methode aufruft, ruft er tatsächlich die erwerbene Methode von AQs auf. Diese Methode erfasst die Sperre als Reaktion auf Fadenunterbrechungen. Der Code für diese Methode ist auch oben veröffentlicht. Wir können sehen, dass in der erwerbenen Methode zunächst die Tryacquireshared -Methode bezeichnet wird, um zu versuchen, das Schloss zu erwerben. Wir sehen die Logik der Tryacquiresharedary -Methode synchronisiert neu. Die Implementierungslogik der Methode ist sehr einfach, nämlich zu beurteilen, ob der aktuelle Synchronisationszustand 0 beträgt. Wenn es 0 ist, bedeutet Rückgabe 1, dass die Sperre erfasst werden kann, ansonsten bedeutet die Rückgabe -1, dass die Sperre nicht erworben werden kann. Wenn die Methode tryAcquireshared -Methode 1 zurückgibt, kann der Thread weiterhin ausgeführt werden, ohne zu warten. Wenn -1 zurückgegeben wird, wird in der synchronen Warteschlange die Methode doacquiresharedinterruptisle aufgerufen, um zu warten. Dies ist das Prinzip, dass das Aufrufen der wartenden Methode den aktuellen Thread blockiert. Lassen Sie uns sehen, wie die Countdown -Methode den Blockierfaden aufweckt.
// Methode zur Reduzierung des Latch -Publikums void Countdown () {sync.releaseshared (1);} // Freisetzung Operation (Shared -Modus) öffentliches endgültiges booleanes releaseshared (int arg) {// 1. Versuchen Sie, die Sperre zu veröffentlichen, wenn (tryReleaseshared (arg)) {// 2. Wenn die Veröffentlichung erfolgreich ist, wecken Sie andere Threads Doreleaseshared () auf; zurückkehren; } return false;}Sie können sehen, dass die methodische Methode in der Countdown -Methode aufgerufen wird. Diese Methode ist auch eine Methode in AQs. Wir haben auch seinen Code darauf gepostet. Das erste, was bei der freigelassenen Methode die tryReleaseshared -Methode aufruft, um das Schloss freizugeben. Die tryReleasesharedared -Methode ist eine abstrakte Methode in AQs. Die spezifische Implementierungslogik befindet sich in der Synchronisierungsklasse der Unterklasse. Wir können diese Methode im oben veröffentlichten Synchronisierungsklassencode finden. Wenn die tryReleasesharedared -Methode zur Veröffentlichung treu zurückgibt und false zurückgibt, um den Fehler zu veröffentlichen. Es wird erst zurückgegeben, wenn der Synchronisationszustand nach Abnahme des Synchronisationszustands genau 0 ist. In anderen Fällen wird False zurückgegeben. Wenn TryReleasesharedared true dann zurückgibt, wird die doreleasesharedary -Methode sofort aufgerufen, um alle Threads in der Synchronisationswarteschlange aufzuwecken. Dies erklärt, warum beim letzten Mal, als die Countdown -Methode aufgerufen wird, um den Zähler auf 0 zu reduzieren, alle blockierten Threads aufwachen. Dies sind die Grundprinzipien von Countdownlatch. Schauen wir uns ein Beispiel für die Verwendung an.
Bewerbungsszenario: Wenn Sie einen glücklichen Vermieter spielen, müssen Sie darauf warten, dass alle drei Spieler ankommen, bevor Sie Karten behandeln können.
Public Class -Spieler erweitert Thread {private statische int count = 1; private endgültige int id = count ++; privater Countdownlatch -Verriegelung; Public Player (Countdownlatch -Latch) {this.latch = latch; } @Override public void run () {System.out.println ("【Player" + id + "] Eintrag"); latch.countdown (); } public static void main (String [] args) löst InterruptedException aus. System.out.println ("Das Spiel beginnt, wartet darauf, dass der Spieler eintritt ..."); neuer Spieler (Latch) .Start (); neuer Spieler (Latch) .Start (); neuer Spieler (Latch) .Start (); latch.aait (); System.out.println ("Die Spieler sind angekommen, mit dem Handeln beginnen ..."); }}Die Betriebsergebnisse zeigen, dass der Handelsvorgang durchgeführt werden muss, nachdem alle Spieler das Feld betreten haben. Wir kommentieren die 23 Zeilenriegel. Await () und vergleichen sie, um die Ergebnisse zu sehen.
Sie können sehen, dass nach dem Aussagen der Linienriegel.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.