Blockieren von Warteschlangen in Java
1. Was ist eine blockierende Warteschlange?
Eine blockierende Warteschlange (Blockingqueue) ist eine Warteschlange, die zwei zusätzliche Operationen unterstützt. Diese zwei zusätzlichen Operationen sind:
Wenn die Warteschlange leer ist, wartet der Thread, der das Element abreißt, darauf, dass die Warteschlange nicht leer wird.
Wenn die Warteschlange voll ist, wartet der Thread, der die Elemente speichert, darauf, dass die Warteschlange verfügbar ist.
Blockierende Warteschlangen werden häufig in Szenarien von Produzenten und Verbrauchern verwendet. Hersteller sind Fäden, die Warteschlangen Elemente hinzufügen, und Verbraucher sind Fäden, die Elemente aus Warteschlangen entnehmen. Eine blockierende Warteschlange ist der Behälter, in dem der Hersteller Elemente speichert und der Verbraucher nur Elemente aus dem Behälter nimmt.
2. Blockieren der Warteschlange in Java
Im JDK sind sieben blockierende Warteschlangen bereitgestellt:
ArrayBlockingqueue
ArrayBlockingQueue ist eine begrenzte Blockierungswarteschlange, die mit Arrays implementiert ist. Diese Warteschlange sortiert Elemente nach dem erstmaligen Prinzip (FIFO). Standardmäßig garantiert die Besucher nicht garantiert fair. Die sogenannte ziemlich zugängliche Warteschlange bezieht sich auf alle blockierten Produzentenfäden oder Verbraucherfäden. Wenn die Warteschlange verfügbar ist, kann in der Reihenfolge der Blockierung auf die Warteschlange zugegriffen werden. Das heißt, der Produzentfaden, der zuerst blockiert, kann zuerst Elemente in die Warteschlange einfügen, und der Konsumentenfaden, der zuerst Elemente blockiert, kann zuerst Elemente erhalten. Normalerweise wird der Durchsatz verringert, um Fairness zu gewährleisten . Mit dem folgenden Code können wir eine faire blockierende Warteschlange erstellen:
ArrayBlockingQueue fairqueue = new ArrayBlockingQueue (1000, true);
Die Fairness seines Zugangs wird durch das Re -Entrantlock -Schloss erreicht.
Linked Blockingqueue
Linked BlockingQueue ist eine begrenzte Blockierungswarteschlange, die mit verknüpften Listen implementiert ist. Die Standard- und maximale Länge dieser Warteschlange ist ganzzahlig.max_value. Diese Warteschlange sortiert Elemente nach dem ersten Prinzip.
Prioritätsblocking
PriorityBlockingQueue ist eine unbegrenzte Warteschlange, die Priorität unterstützt. Standardmäßig sind Elemente in natürlicher Reihenfolge angeordnet, und die Bestellregeln von Elementen können auch über den Komparatorvergleich angegeben werden. Die Elemente sind in aufsteigender Reihenfolge angeordnet.
Verzögerung
DelayQueue ist eine unbegrenzte Blockierungswarteschlange, die eine verzögerte Erwerb von Elementen unterstützt. Die Warteschlange wird mit Prioritätsqueue implementiert. Elemente in der Warteschlange müssen die verzögerte Schnittstelle implementieren, und beim Erstellen eines Elements können Sie angeben, wie lange es dauert, um das aktuelle Element aus der Warteschlange zu erhalten. Elemente können nur aus der Warteschlange extrahiert werden, wenn die Verzögerung abläuft. In den folgenden Anwendungsszenarien können wir Delayqueue verwenden:
Design des Cache -Systems: DelayQueue kann verwendet werden, um die Gültigkeitsdauer von Cache -Elementen zu speichern, und ein Thread kann verwendet werden, um die Verzögerung abzufragen. Sobald das Element aus dem Verzögerungsqueue erhalten werden kann, bedeutet dies, dass die Gültigkeitsdauer des Cache eingetroffen ist.
Geplanter Aufgabenplan. Verwenden Sie DelayQueue, um die am Tag ausgeführten Aufgaben und Ausführungszeiten zu speichern. Sobald die Aufgabe aus dem Delayqueue erfasst wurde, beginnt sie auszuführen. Zum Beispiel wird Timerqueue unter Verwendung von Delayqueue implementiert.
So implementieren Sie die verzögerte Schnittstelle
Wir können uns auf die enderfuturetask -Klasse in ScheduledThreadpoolexecutor beziehen. Diese Klasse implementiert die verzögerte Schnittstelle. Erstens: Wenn Sie ein Objekt erstellen, nutzen Sie die Zeit, um aufzuzeichnen, wenn das Objekt vor der Aufnahme verwendet werden kann. Der Code ist wie folgt:
AfuledFuturetask (Runnable r, v Ergebnis, langer ns, langer Zeitraum) {Super (r, Ergebnis); thattime = ns; this.period = Periode; this.sequencenumber = sequencer.getandIncrement ();}Verwenden Sie dann GetDelay, um zu fragen, wie lange das aktuelle Element verzögert werden muss. Der Code ist wie folgt:
public Long getDelay (Zeitunit Unit) {return Unit.Convert (Zeit - Now (), Timeunit.Nanoseconds); }Durch den Konstruktor können wir sehen, dass die Einheit des Verzögerungszeitparameters NS Nanosekunden ist. Es ist am besten, Nanosekunden beim Entwerfen selbst zu verwenden, da Sie beim Abrufen eines Geräts eine Einheit angeben können. Sobald Nanosekunden als Einheit verwendet werden und die Verzögerungszeit weniger als Nanosekunden beträgt, wird dies problematisch sein. Bitte beachten Sie, dass GetDelay eine negative Zahl zurückgibt, wenn die Zeit geringer als die aktuelle Zeit ist.
Schließlich können wir Zeit verwenden, um die Reihenfolge in der Warteschlange anzugeben, zum Beispiel: Lassen Sie die längste Verzögerungszeit am Ende der Warteschlange platziert werden.
public int vergleicheto (verspätete andere) {if (other == this) return 0; if (andere Instanzen von teplanedFuturetask) {afulledFuturetask x = (afulledFuturetask) Andere; lange diff = Zeit - X.Time; if (diff <0) return -1; sonst wenn (diff> 0) zurücksender 1; sonst wenn (sequencEnumber <x.sequencenumber) return -1; sonst return 1; } long d = (getDelay (TimeUnit.Nanoseconds) -Other.getDelay (TimeUnit.Nanoseconds)); return (d == 0)? 0: (d <0)? -1: 1); }So implementieren Sie verzögerte blockierende Warteschlangen
Die Implementierung der Verzögerungsblockierung von Warteschlangen ist sehr einfach. Wenn der Verbraucher Elemente aus der Warteschlange erhält und das Element die Verzögerungszeit nicht erreicht, blockiert es den aktuellen Thread.
Long Delay = First.getDelay (timeutil.nanosekunden); if (delay <= 0) {return q.poll; // blockierende Warteschlange} else if (Leader! // Lassen Sie den Thread das Wartesignal eingeben} else {// Wenn der Anführer null ist, setzen Sie den aktuellen Thread auf die Führungsthread. }}}Synchronousqueue
Synchronousqueue ist eine blockierende Warteschlange, die keine Elemente speichert. Jede Put -Operation muss auf einen Einnahmebetrieb warten, andernfalls können die Elemente nicht hinzugefügt werden. Synchronousqueue kann als Passant angesehen werden, der für die Übergabe von Daten verantwortlich ist, die vom Produzenten -Thread direkt an den Verbraucher -Thread verarbeitet wurden. Die Warteschlange selbst speichert keine Elemente, die für transitive Szenarien sehr geeignet sind. Beispielsweise werden Daten, die in einem Thread verwendet werden, zur Verwendung an einen anderen Thread übergeben. Der Durchsatz von Synchronousqueue ist höher als der von
Linked Blockingqueue und ArrayBlockingQueue.
Es unterstützt Warteschlangen für den fairen Zugang. Standardmäßig ist es immer noch ein unfairer politischer Mechanismus
LinkedTransferqueue
LinkedTransferQueue ist eine unbegrenzte Blockierung von Transferqueue -Warteschlangen, die aus der verknüpften Listenstruktur besteht. Im Vergleich zu anderen blockierenden Warteschlangen verfügt LinkedTransferqueue über mehr Trypransfer- und Transfermethoden.
Übertragungsmethode
Wenn ein Verbraucher derzeit darauf wartet, ein Element zu empfangen (wenn der Verbraucher die Methode take () oder die zeitlich begrenzte Poll () -Methode) verwendet, kann die Übertragungsmethode die vom Hersteller übergebenen Elemente sofort an den Verbraucher übertragen. Wenn kein Verbraucher auf das empfangende Element wartet, speichert die Übertragungsmethode das Element im Heckknoten der Warteschlange und wartet, bis das Element vor der Rückkehr vom Verbraucher verzehrt wird.
Trypransfer -Methode
Es wird verwendet, um zu testen, ob die vom Hersteller eingeführten Elemente direkt an den Verbraucher übertragen werden können. Wenn kein Verbraucher auf das empfangende Element wartet, wird FALSE zurückgegeben. Der Unterschied zwischen der Übertragungsmethode besteht darin, dass die Trytransfer -Methode sofort zurückgibt, unabhängig davon, ob der Verbraucher sie empfängt oder nicht. Die Übertragungsmethode muss warten, bis der Verbraucher sie vor der Rückkehr konsumiert.
Für die Trytransfer -Methode (e e, langfristig, langfristig, Zeiteinheit) mit Zeitlimit versucht sie, das vom Hersteller direkt an den Verbraucher übergebene Element zu übergeben. Wenn jedoch kein Verbraucher das Element konsumiert, wartet es auf die angegebene Zeit vor der Rückkehr. Wenn das Timeout das Element nicht konsumiert hat, wird falsch zurückgegeben, und wenn das Element innerhalb der Zeitüberschreitungszeit verzehrt wird, wird es wahr zurückgegeben.
Linked BlockingDeque
Linked BlockingDeque ist eine bidirektionale Blockierungswarteschlange, die aus der verknüpften Listenstruktur besteht. Die sogenannte Zwei-Wege-Warteschlange bezieht sich auf die Tatsache, dass Sie Elemente an beiden Enden der Warteschlange einfügen und entfernen können. Da die Doppel-Warteschlange einen zusätzlichen Einstieg in die Operation Warteschlange hat, wird die Konkurrenz um die Hälfte reduziert, wenn mehrere Threads gleichzeitig der Warteschlange beitreten. Im Vergleich zu anderen blockierenden Warteschlangen verfügt LinkedBlockingDeque über mehr Addlast, Offerfirst, Offer -Offer-, Peekfirst, Peeklast und andere Methoden. Die Methode endet mit dem ersten Wort, zeigt Insertion, Erwerb oder Entfernung des ersten Elements der Doppel-Endwarteschlange an. Eine Methode, die mit dem letzten Wort endet, das angibt, dass das letzte Element der doppelten Warteschlange eingefügt, erhalten oder entfernt wird. Zusätzlich entspricht die Einfügungsmethode AddLast und das Entfernen der Entfernung entspricht dem Entfernen. Die Take -Methode entspricht jedoch TakeFirst. Ich weiß nicht, ob es sich um einen Fehler in JDK handelt, und es ist klarer, die Methode mit den ersten und letzten Suffixen bei der Verwendung zu verwenden. Die Kapazität der Warteschlange kann bei der Initialisierung von LinkedBlockingDeque initialisiert werden, um zu verhindern, dass sie anschwellung, wenn sie wieder aufgenommen wird. Darüber hinaus kann die bidirektionale Blockierungswarteschlange im "Arbeitsdiebstahl" -Modus verwendet werden.
Danke fürs Lesen, ich hoffe, es kann Ihnen helfen. Vielen Dank für Ihre Unterstützung für diese Seite!