JavaRush /Java-Blog /Random-DE /SynchronousQueue-Beispiel in Java – Lösung des Problems P...
profeg
Level 18

SynchronousQueue-Beispiel in Java – Lösung des Problems Producer Consumer

Veröffentlicht in der Gruppe Random-DE
SynchronousQueue-Beispiel in Java – Lösung des Problems Producer Consumer
SynchronousQueue ist eine spezielle Art von BlockingQueue, bei der jeder Einfügungsvorgang auf einen entsprechenden Entfernungsbefehl in einem anderen Thread warten muss und umgekehrt. Wenn Sie die put()-Methode für eine SynchronousQueue aufrufen, blockiert sie, bis ein anderer Thread dieses Element daraus übernimmt. Wenn also ein anderer Thread versucht, ein Element daraus zu entfernen, und das Element nicht vorhanden ist, blockiert dieser Thread , bis der andere Thread das Element in die Warteschlange stellt. Sie können sich SynchronousQueue als einen Athleten ( Thread ) vorstellen, der mit der olympischen Fackel rennt, er läuft mit der Fackel (dem Objekt, das weitergegeben wird) und gibt sie an einen anderen Athleten weiter, der auf der anderen Seite wartet. Wenn Sie auf den Namen achten, werden Sie verstehen, dass SynchronousQueue aus einem bestimmten Grund so heißt: Es überträgt Daten synchron an einen anderen Thread . Es wartet darauf, dass jemand die Daten abholt, anstatt sie einfach einzugeben und zu beenden (ein asynchroner Vorgang). Wenn Sie mit CSP und Ada vertraut sind, wissen Sie, dass synchronisierte Warteschlangen dem Treffen von Threads ähneln. Sie eignen sich gut für Kontrollübertragungskonstrukte, bei denen ein in einem Thread ausgeführtes Objekt mit einem Objekt in einem anderen Thread synchronisiert werden muss, um Informationen, Ereignisse oder Aufgaben an dieses zu übergeben. In früheren Tutorials zur Multithread-Programmierung haben wir gelernt, wie man das Producer-Consumer-Problem mithilfe der Methoden „wait and notify“ und „BlockingQueue“ löst . Jetzt lernen wir, wie man das Producer-Consumer-Muster mit SynchronousQueue anwendet. Diese Klasse unterstützt außerdem faires Verhalten für die Reihenfolge der Wartevorgänge der Producer- und Consumer-Threads. Standardmäßig ist diese Reihenfolge nicht garantiert. Mit fairen Eigenschaften erstellte Warteschlangen garantieren jedoch den Zugriff für Threads in einer FIFO- Warteschlange (Firs In First Out).
Produzent/Konsumer mit SynchronousQueue in Java.
SynchronousQueue-Beispiel in Java – Lösung des Problems Producer Consumer – 1 Wie ich oben sagte, gibt es nichts Besseres als das Producer-Consumer-Problem, um die Kommunikation zwischen Threads in jeder Programmiersprache zu verstehen. Bei diesem Problem fungiert ein Thread als Produzent, der Ereignisse und Aufgaben produziert, und der andere Thread fungiert als Konsument davon. Ein gemeinsamer Puffer wird verwendet, um Daten vom Produzenten zum Verbraucher zu übertragen. Die Schwierigkeit, dieses Problem zu lösen, tritt in extremen Fällen auf, beispielsweise wenn der Hersteller gezwungen ist, zu warten, weil ... Der Puffer ist voll oder der Verbraucher muss warten, weil der Puffer ist leer. Das war leicht zu lösen, weil... Die Blockierungswarteschlange stellte nicht nur einen Puffer zum Speichern von Daten bereit, sondern auch eine Flusskontrolle, indem sie den Thread blockierte, der die Methode put() aufrief (Produzent), wenn der Puffer voll war, und den Thread blockierte, der die Methode take() aufrief (Verbraucher), wenn der Puffer war leer. Jetzt werden wir dasselbe Problem mit SynchronousQueue lösen, einer besonderen Art paralleler Sammlungen ohne Kapazität. Im folgenden Beispiel haben wir zwei Threads namens PRODUCER und CONSUMER (geben Sie den Threads immer Namen, dies ist ein sehr guter Stil der Multithread-Programmierung). Der erste Thread postet die Punktzahl im Spiel und der zweite Thread verbraucht sie. Die Punktzahl im Spiel ist nichts anderes als ein Objekt vom Typ String. Wenn Sie das Programm jedoch mit einem anderen Typ ausführen, werden Sie keinen Unterschied bemerken. Um zu verstehen, wie SynchronousQueue funktioniert und wie das Producer-Consumer-Problem gelöst werden kann, müssen Sie: entweder das Programm zum Debuggen (Debuggen) in der Eclipse-Umgebung ausführen oder einfach den Producer-Thread starten, indem Sie Consumer.start(); Wenn der Consumer-Thread nicht ausgeführt wird, wird der Producer-Thread bei queue.put(event) blockiert. Wenn es ausgeführt wird, können Sie nicht sehen, dass der Produzent [PRODUCER] das :FOUR-Ereignis veröffentlicht. Dies geschieht, weil Spezifisches Verhalten von SynchronousQueue, das sicherstellt, dass der Thread, der Daten postet, blockiert, bis ein anderer Thread die Daten übernimmt, und umgekehrt. Sie können den Rest des Codes testen, indem Sie Producer.start(); auskommentieren. und nur den Consumer-Thread starten. Wenn Sie sorgfältig studieren, was das Programm ausgibt, werden Sie feststellen, dass die Reihenfolge der Ausgabe umgekehrt ist. Es sieht so aus, als hätte der [CONSUMER] -Thread die Daten übernommen, bevor der [PRODUCER] -Thread sie erzeugt hat. Dies liegt daran, dass SynchronousQueue standardmäßig keine Warteschlange garantiert. Es gibt jedoch Fairnessregeln, die den Zugriff auf Threads in der FIFO-Reihenfolge festlegen. Sie können diese Regeln aktivieren, indem Sie true wie folgt an den überladenen SynchronousQueue-Konstruktor übergeben: import java.util.concurrent.SynchronousQueue; /** * Java Program to solve Producer Consumer problem using SynchronousQueue. A * call to put() will block until there is a corresponding thread to take() that * element. * * @author Javin Paul */ public class SynchronousQueueDemo{ public static void main(String args[]) { final SynchronousQueue queue = new SynchronousQueue (); Thread producer = new Thread("PRODUCER") { public void run() { String event = "FOUR"; try { queue.put(event); // thread will block here System.out.printf("[%s] published event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; producer.start(); // starting publisher thread Thread consumer = new Thread("CONSUMER") { public void run() { try { String event = queue.take(); // thread will block here System.out.printf("[%s] consumed event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; consumer.start(); // starting consumer thread } } Output: [CONSUMER] consumed event : FOUR [PRODUCER] published event : FOUR new SynchronousQueue(boolean fair).
Was Sie über SynchronousQueue in Java beachten müssen.

Hier sind einige wichtige Eigenschaften dieser speziellen Art von Blockierungswarteschlange in Java. Es ist sehr nützlich, Daten synchronisiert von einem Thread an einen anderen zu übergeben. Diese Warteschlange hat keine Kapazität und ist blockiert, bis ein anderer Thread sie freigibt.

  1. SynchronousQueue blockiert, und bis ein Thread bereit ist, Daten aufzunehmen, versucht ein anderer, Daten einzugeben.
  2. SynchronousQueue hat kein Volume. Das heißt, es enthält keine Daten.
  3. SynchronousQueue wird verwendet, um eine Vorwärtswarteschlangenstrategie zu implementieren, bei der ein Thread die Kontrolle an einen wartenden Thread übergibt oder einen neuen erstellt, wenn dies zulässig ist. Andernfalls wird die Kontrolle nicht übertragen.
  4. Diese Warteschlange lässt keine Nulldaten zu. Der Versuch, ein Nullelement hinzuzufügen, löst eine NullPointerException aus .
  5. Wenn Sie andere Methoden aus der Sammlung verwenden (z. B. enthält), verhält sich SynchronousQueue wie eine leere Sammlung.
  6. Sie können die Peek-Methode von SynchronousQueue nicht verwenden, da das Element nur dann vorhanden ist, wenn Sie versuchen, es zu entfernen. Außerdem können Sie keine Elemente einfügen (mit welcher Methode auch immer), bis ein anderer Thread versucht, sie zu entfernen.
  7. Sie können den Iterator nicht für SynchronousQueue verwenden, weil ... es hat keine Elemente.
  8. SynchronousQueue kann mit fairen Regeln erstellt werden, bei denen der Zugriff auf Threads in FIFO-Reihenfolge garantiert ist.
Vielleicht dreht sich hier alles um SynchronousQueue in Java. Wir haben uns einige der Besonderheiten dieser Multithread-Sammlung angesehen und gelernt, wie man das klassische Producer-Consumer-Problem mithilfe von SynchronousQueue in Java löst. Es ist übrigens nicht ganz korrekt, es eine Warteschlange zu nennen, denn... es enthält keine Elemente. Der Aufruf von put() wird erst abgeschlossen, wenn ein anderer Thread take() aufruft. Es ist richtiger, es sich als einen Treffpunkt von Fäden vorzustellen, an dem sie ein gemeinsames Objekt haben. Mit anderen Worten handelt es sich um ein Dienstprogramm zur synchronisierten Übergabe von Objekten in Java, möglicherweise eine sicherere Alternative zur Methode „wait“ und „notify“ .
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION