Was wäre ein Einsatz von DelayQueue in der realen Welt , welches häufige Problem sollte damit gelöst werden?
Was wäre ein Einsatz von DelayQueue in der realen Welt , welches häufige Problem sollte damit gelöst werden?
Antworten:
Ich habe kürzlich eine Verzögerungswarteschlange zur Ratenbegrenzung verwendet.
Platzieren Sie für ein Limit von X Ereignissen pro Sekunde jedes Ereignis mit einer Verzögerung von 1 Sekunde in einer Verzögerungswarteschlange.
Wenn die delayQueue X Ereignisse enthält, nehmen Sie () aus der Warteschlange (die blockiert, bis mindestens 1 abläuft). Auf diese Weise können Sie einen kurzfristigen Burst zulassen, ohne langfristige Grenzwerte zu überschreiten.
Diese Klasse ist perfekt für einen Thread, der mehrere verzögerte Ereignisse in der richtigen Reihenfolge verarbeiten möchte.
Angenommen, Sie haben ein Display mit 100 blinkenden Lichtern und alle Lichter blinken mit unterschiedlichen, unabhängigen Raten. Sie könnten einen Thread für jedes Licht haben, oder Sie könnten einen Thread haben, der alle mit dieser Klasse koordiniert. Es würde ungefähr so funktionieren:
Light
Klasse mit einer BlitzrateDelayed
Schnittstelle, die beispielsweise auf das Licht verweistLightFlash
DelayQueue
und fügen Sie LightFlash
für jedes Licht eine neue hinzu , wobei die Verzögerung auf die Blitzrate des Lichts abgestimmt istDelayQueue sorgt dafür, dass das nächste Ereignis verarbeitet wird.
Zwei Beispiele aus der Praxis, die mir einfallen:
DelayQueue
wird wahrscheinlich als Prioritätswarteschlange implementiert , die im Allgemeinen am besten als Heap implementiert wird .
Die Hauptverwendung wären Task-Timer wie die für Timer-Klassen
Wenn man die Verzögerung von der Systemuhr unabhängig machen könnte (was ich glaube, aber nicht sicher bin), kann man sie für Spielereignisse wie "Nach 5 Ticks auf X verschieben" verwenden (andernfalls würde Clock Jitter dies unzuverlässig machen).
Beachten Sie, dass die Verzögerungen eher mit den Elementen in der Warteschlange als mit der Warteschlange selbst verknüpft sind. Einige Objekte, die in die Warteschlange gestellt werden, können eine Verzögerung von Null aufweisen, während andere eine wesentlich längere Verzögerung aufweisen können:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Delayed.html
In diesem Sinne kann ich mir einige Anwendungsfälle vorstellen - obwohl sie wahrscheinlich zerbrechlich sind und in Bezug auf Ihren Nachrichtenfluss ein bisschen nach Code riechen. Ich würde Alternativen zu allen verwenden, außer in bestimmten Situationen:
1) Kontrollfluss - Wir wissen, dass die Verarbeitung eines Auftrags 60 Sekunden dauert. Lesen Sie daher den nächsten Auftrag erst aus der Warteschlange, wenn das Objekt mindestens 60 Sekunden dort war.
2) Nachrichtenfluss - Ein stark asynchrones System, bei dem wir Anfragen an zwei oder drei externe Dienste senden und dann die nächste Aufgabe freigeben, um den Auftrag N Sekunden später zu verarbeiten, sobald wir wissen, dass der erste Stapel von Aufträgen zumindest die Chance hat, abgeschlossen zu werden .
3) Stapelverarbeitung von Nachrichten - Möglicherweise sind Aufträge eines bestimmten Typs unvollständig, sodass Aufträge, die in den letzten N Sekunden eingegangen sind, nicht verarbeitet werden können. So können wir feststellen, ob ähnliche Aufträge kurz darauf eingehen und beim nächsten Durchlauf als Stapel verarbeitet werden können.
4) Nachrichtenprioritäten - Unterschiedliche Nachrichten oder unterschiedliche Kunden können eine geringfügig höhere Dienstqualität mit einer geringeren oder nullten Verzögerung erzielen.
In einigen Fällen sollten sich Objekte, die Sie in eine Warteschlange stellen, eine bestimmte Zeit lang in dieser Warteschlange befinden, bevor sie in die Warteschlange gestellt werden können. Hier verwenden Sie die Klasse java.util.concurrent.DelayQueue, die die BlockingQueue-Schnittstelle implementiert. Für die DelayQueue müssen sich die Warteschlangenobjekte eine bestimmte Zeit lang in der Warteschlange befinden.
Ein Beispiel für die Verwendung in der Praxis finden Sie im Artikel Warteschlange bearbeiten auf der devx-Site
... Das reale Beispiel, an dem ich dachte, um dies zu veranschaulichen (was Sie hungrig machen könnte), beinhaltet Muffins. Nun, Muffin-Objekte (während wir über Java sprechen - kein Kaffee-Wortspiel beabsichtigt). Angenommen, Sie haben eine DelayQueue, auf der Sie Muffin-Objekte platzieren ... Die Methode getDelay gibt im Wesentlichen an, wie viel Zeit für die Aufbewahrung des Objekts in der DelayQueue verbleibt. Wenn die von dieser Methode zurückgegebene Zahl Null oder kleiner als Null ist, ist das Objekt bereit (oder in diesem Beispiel gebacken) und kann aus der Warteschlange entfernt werden.
Da Sie nicht wirklich ein Muffin essen möchten, das noch nicht vollständig gekocht ist, legen Sie das Muffin für die empfohlene Garzeit auf die DelayQueue ...