Die Funktion der Bedingung besteht darin, eine genauere Kontrolle über das Schloss zu liefern. Die Warte () -Methode im Zustand entspricht der Warte () -Methode des Objekts, die Signal () -Methode im Zustand entspricht der Objektmethode von Notify (), und die SignalAll () im Zustand entspricht der Notifyall () -Methode des Objekts. Der Unterschied besteht darin, dass die Methoden Wait (), Notify () und Notifyall () in Objekt mit "Synchronisierter Schloss" (synchronisiertes Schlüsselwort) gebündelt sind. und der Zustand muss mit "Mutex"/"Share Lock" gebündelt werden.
Bedingungsfunktionsliste
// lässt den aktuellen Thread warten, bis er ein Signal empfängt oder unterbrochen wird. Void wartet () // lässt den aktuellen Faden in einem Wartezustand bleiben, bevor ein Signal unterbrochen wird oder die angegebene Wartezeit erreicht. Boolean wartet (lange Zeit, Zeiteinheit) // führt dazu, dass der aktuelle Faden in einem Wartezustand befindet, bis er ein Signal empfängt, unterbrochen wird oder die angegebene Wartezeit erreicht. Lange erwartetnanos (lange Nanostimeout) // führt dazu, dass der aktuelle Faden in einem Wartezustand befindet, bevor das Signal empfangen wird. Void AwaitUtuninterrupticled () // lässt den aktuellen Thread in einem Wartezustand bleiben, bis er ein Signal empfängt, unterbrochen wird oder die angegebene Frist erreicht. boolean wartungil (Datum Frist) // einen wartenden Thread aufwecken. void signal () // wach alle wartenden Fäden auf. void signalall ()
Beispiel für Bedingungsklassennutzung
Die Bedingung unterteilt die Objektmonitormethoden (warten, benachrichtigen und benachrichtigen) in völlig unterschiedliche Objekte, so dass jedes Objekt durch Kombination dieser Objekte mit einer beliebigen Sperrimplementierung mehrere Wartezeitsätze (Wartezeiten) bietet. Unter ihnen ersetzt die Sperre die Verwendung synchronisierter Methoden und Aussagen und der Zustand ersetzt die Verwendung von Objektmonitormethoden. Das Folgende ist ein zuvor geschriebenes Beispiel für die Kommunikation von Threads mit der Implementierung mit Bedingung. Der Code lautet wie folgt:
public class threadTest2 {public static void main (String [] args) {Final Business Business = new Business (); neuer Thread (new Runnable () {@Override public void run () {threadExecute (Business, "sub");}}). start (); ThreadExecute (Business, "Main"); } public static void threadExecute (Business Business, String threadType) {für (int i = 0; i <100; i ++) {try {if ("main" .equals (threadType)) {business.main (i); } else {Business.sub (i); }} catch (interruptedException e) {e.printstacktrace (); }}}} Klasse Business {private boolean bool = true; Private Lock Lock = New Reentrantlock (); private Bedingung Zustand = lock.newCondition (); public /*synchronisiert* / void main (int loop) löscht InterruptedException {lock.lock (); try {while (bool) {condition.await (); // this.wait (); } für (int i = 0; i <100; i ++) {System.out.println ("Hauptsthread seq von" + i + ", Schleife von" + Loop); } bool = true; Condition.Signal (); // this.notify (); } endlich {lock.unlock (); }} public /*synchronisiert* / void sub (int loop) löscht InterruptedException {lock.lock (); try {while (! bool) {condition.await (); // this.wait (); } für (int i = 0; i <10; i ++) {System.out.println ("Sub -Thread seq von" + i + ", Schleife von" + Loop); } bool = false; Condition.Signal (); // this.notify (); } endlich {lock.unlock (); }}} Ersetzen Sie im Zustand Wait () durch Await (), ersetzen Sie benachrichtigen () durch Signal () und ersetzen Sie NotifyAll () durch SignalAll (). Die traditionelle Kommunikationsmethode von Threads kann implementiert werden. Beachten Sie hier, dass die Bedingung an ein Schloss gebunden ist. Um ein Schloss zu erstellen, müssen Sie die Methode NewCondition () verwenden.
Auf diese Weise unterscheidet sich der Zustand nicht von der traditionellen Thread -Kommunikation. Die Kraft der Bedingung besteht darin, dass sie unterschiedliche Bedingungen zwischen mehreren Threads festlegen kann. Das Folgende ist ein Code aus der API, das illustriert werden soll.
class BoundedBuffer { final Lock lock = new ReentrantLock();//Lock object final Condition notFull = lock.newCondition();//Write thread condition final Condition notEmpty = lock.newCondition();//Read thread condition final Object[] items = new Object[100];//Cached queue int putptr/*Write index*/, takeptr/*Read index*/, count/*Number of data exists in die Warteschlange*/; public void put (Objekt x) löscht InterruptedException {lock.lock (); Versuchen Sie {while (count == items.length) // Wenn die Warteschlange nicht von Notfull.await (); // Blockieren Sie die Schreib -Thread -Elemente [putptr] = x; // zuweisen if (++ putptr == items.Length) putptr = 0; // Wenn der Schreibindex an die letzte Position des Queues wak. Thread} endlich {lock.unlock (); }} öffentliches Objekt take () löscht InterruptedException {lock.lock (); Versuchen Sie {while (count == 0) // Wenn die Warteschlange leer ist. X; } endlich {lock.unlock (); }}} Dies ist ein Cache-Bereich in einer Arbeitsumgebung mit mehreren Threaden. Der Cache -Bereich bietet zwei Methoden: Setzen und Nehmen. Das Speichern von Daten besteht darin, Daten abzurufen, und es gibt eine Cache -Warteschlange im Inneren. Weitere Variablen und Methodenbeschreibungen finden Sie im Code. Die von dieser Cache -Bereichsklasse implementierten Funktionen: Mehrere Threads speichern Daten und rufen Daten daraus ab. Der maximale Cache -Wert, den die Cache -Warteschlange (zuerst in, zuerst heraus, dann in und dann heraus) Cache beträgt, beträgt 100. Mehrere Threads schließen sich gegenseitig aus. Wenn der in der Cache -Warteschlange gespeicherte Wert 100 erreicht wird, wird der Schreib Thread blockiert und der Lesedhreop wird geweckt. Wenn der in der Cache -Warteschlange gespeicherte Wert 0 beträgt, wird der Lese -Thread blockiert und der Schreibphread wird geweckt. Die folgende Analyse des Codeausführungsprozesses:
1. Ein Schreib Thread führt und ruft die Put -Methode aus;
2. Um festzustellen, ob die Anzahl 100 ist, gibt es offensichtlich keine 100;
3. Ausführen und zahlen Sie den Wert weiter aus;
4. Nachdem die aktuell geschriebene Indexposition ++ ermittelt wurde, entspricht er den Schreibindexwert auf 0 und zählt+1;
5. Wach nur einen der Lesefaden auf, die Warteschlangen blockieren;
6. Führen Sie einen Lese -Thread aus und rufen Sie die Methode Take auf.
7.…
8. Wach nur einen der Write -Thread -Blockierwarteschlangen auf.
Dies ist die Kraft mehrerer Bedingungen. Unter der Annahme, dass die Cache-Warteschlange voll ist, ist die Blockierung definitiv der Schreibbefugnis, und das Weck-up ist definitiv der Lese-Thread. Im Gegenteil, die Blockierung ist definitiv der Lese-Thread und das Weck-up ist definitiv der Schreib Thread. Was wird also passieren, wenn es nur einen Zustand gibt? Die Cache -Warteschlange ist voll, diese Sperre weiß nicht, ob es sich um den Lese -Thread oder der Schreibbefugnis handelt. Wenn das Aufwachen der Lese-Thread ist, ist jeder glücklich. Wenn das Weck-up der Schreib Thread ist, wurde der Thread gerade wieder geweckt und blockiert und wacht dann wieder auf, was viel Zeit verschwendet.