Útmutató a DelayQueue-hoz
1. Áttekintés
Ebben a cikkben megnézzük a DelayQueue konstruálni a java.util.egyidejű csomag. Ez egy blokkoló sor, amelyet fel lehet használni a termelő-fogyasztó programokban.
Nagyon hasznos jellemzője van - amikor a fogyasztó egy elemet el akar venni a sorból, akkor csak akkor veheti el, amikor az adott elem késése lejárt.
2. Végrehajtás Késleltetett elemei számára a DelayQueue
Minden elem, amelyet be akarunk helyezni DelayQueue végre kell hajtania a Késleltetett felület. Tegyük fel, hogy a DelayObject osztály. Az adott osztály példányai bekerülnek a DelayQueue.
Át fogjuk adni a Húr adatok és késésMilliszekundumban és érvek a konstruktőre:
public class A DelayObject megvalósítja a Delayed {private String data; privát hosszú kezdési idő; public DelayObject (String adatok, hosszú késésInMilliseconds) {this.data = adatok; this.startTime = System.currentTimeMillis () + delayInMilliseconds; }
Meghatározzuk a kezdési idő - ez az az idő, amikor az elemet a sorból kell fogyasztani. Ezután végre kell hajtanunk a getDelay () metódus - vissza kell adnia az objektumhoz tartozó fennmaradó késleltetést az adott időegységben.
Ezért használnunk kell a TimeUnit.convert () módszer a fennmaradó késleltetés visszaadásához TimeUnit:
@Orride public long getDelay (TimeUnit unit) {long diff = startTime - System.currentTimeMillis (); return unit.convert (diff, TimeUnit.MILLISECONDS); }
Amikor a fogyasztó megpróbál egy elemet kivenni a sorból, a DelayQueue végrehajtja getDelay () megtudni, hogy az elemet szabad-e visszaküldeni a sorból. Ha a getDelay () metódus nulla vagy negatív számot ad vissza, ez azt jelenti, hogy lehívható a sorból.
Meg kell valósítanunk a összehasonlítani() módszer, mert az elemeket a DelayQueue a lejárati idő szerint lesz rendezve. Az elsőként lejáró elemet a sor élén tartják, a legmagasabb lejárati idővel rendelkező elemet pedig a sor farka:
@Orride public int CompareTo (Delayed o) {return Ints.saturatedCast (this.startTime - ((DelayObject) o) .startTime); }
3. C késleltetési soronsumer és Producer
Hogy tesztelhessük a mi DelayQueue meg kell valósítanunk a termelői és a fogyasztói logikát. A producerkategória a várakozási sort, az előállítandó elemek számát és az egyes üzenetek késleltetését ezredmásodpercben veszi figyelembe argumentumként.
Majd amikor a fuss() A metódus meghívásra kerül, az elemeket a sorba helyezi, és 500 milliszekundumig alszik minden egyes elrendezés után:
public class DelayQueueProducer megvalósítja a Runnable {private BlockingQueue queue; privát Egész szám numberOfElementsToProduce; private Integer delayOfEachProducedMessageMilliseconds; // standard konstruktor @ Override public void run () {for (int i = 0; i <numberOfElementsToProduce; i ++) {DelayObject objektum = új DelayObject (UUID.randomUUID (). toString (), delayOfEachProducedMessageMilliseconds); System.out.println ("Objektum felhelyezése:" + objektum); próbáld ki a {queue.put (objektum); Szál.alszik (500); } catch (InterruptedException ie) {ie.printStackTrace (); }}}}
A fogyasztói megvalósítás nagyon hasonló, de nyomon követi az elfogyasztott üzenetek számát is:
public class DelayQueueConsumer megvalósítja a Runnable {private BlockingQueue queue; privát Egész szám numberOfElementsToTake; public AtomicInteger numberOfConsumedElements = new AtomicInteger (); // szabványos konstruktorok @Override public void run () {for (int i = 0; i <numberOfElementsToTake; i ++) {próbálkozzon {DelayObject object = queue.take (); numberOfConsumedElements.incrementAndGet (); System.out.println ("Fogyasztó felvétele:" + objektum); } catch (InterruptedException e) {e.printStackTrace (); }}}}
4. DelayQueue Használat teszt
A. Viselkedésének tesztelésére DelayQueue, létrehozunk egy gyártói szálat és egy fogyasztói szálat.
A producer fogja put () két objektum a sorba 500 milliszekundum késéssel. A teszt azt állítja, hogy a fogyasztó két üzenetet fogyasztott:
@Test public void givenDelayQueue_whenProduceElement _thenShouldConsumeAfterGivenDelay () thrumps InterruptedException {// adott ExecutorService végrehajtó = Executors.newFixedThreadPool (2); BlockingQueue queue = new DelayQueue (); int numberOfElementsToProduce = 2; int delayOfEachProducedMessageMilliseconds = 500; DelayQueueConsumer fogyasztó = new DelayQueueConsumer (sor, numberOfElementsToProduce); DelayQueueProducer producer = új DelayQueueProducer (sor, numberOfElementsToProduce, delayOfEachProducedMessageMilliseconds); // amikor végrehajtó.beküldés (producer); végrehajtó.beküldés (fogyasztó); // majd végrehajtó.awaitTermination (5, TimeUnit.SECONDS); végrehajtó.leállítás (); assertEquals (consumer.numberOfConsumedElements.get (), numberOfElementsToProduce); }
Megfigyelhetjük, hogy a program futtatása a következő kimenetet eredményezi:
Objektum felhelyezése: {data = '86046157-e8a0-49b2-9cbb-8326124bcab8', startTime = 1494069868007} Fogyasztói felvétel: {data = '86046157-e8a0-49b2-9cbb-8326124bcab8', startTime = 149406986800 'd47927ef-18c7-449b-b491-5ff30e6795ed', startTime = 1494069868512} Fogyasztói vásárlás: {data = 'd47927ef-18c7-449b-b491-5ff30e6795ed', startTime = 1494069868512}
A gyártó leteszi az objektumot, és egy idő után elfogyasztja az első tárgyat, amelynél a késés lejárt.
Ugyanez történt a második elemnél is.
5. A fogyasztó az adott idő alatt nem képes fogyasztani
Tegyük fel, hogy van olyan termelőnk, amely olyan elemet állít elő, amely fog 10 másodpercen belül lejár:
int numberOfElementsToProduce = 1; int delayOfEachProducedMessageMilliseconds = 10_000; DelayQueueConsumer fogyasztó = new DelayQueueConsumer (sor, numberOfElementsToProduce); DelayQueueProducer producer = új DelayQueueProducer (sor, numberOfElementsToProduce, delayOfEachProducedMessageMilliseconds);
Elkezdjük a tesztünket, de 5 másodperc múlva leáll. A. Jellemzői miatt DelayQueue, a fogyasztó nem tudja felhasználni az üzenetet a sorból, mert az elem még nem járt le:
végrehajtó.beküldés (producer); végrehajtó.beküldés (fogyasztó); végrehajtó.awaitTermination (5, TimeUnit.SECONDS); végrehajtó.leállítás (); assertEquals (fogyasztó.számOfConsumedElements.get (), 0);
Ne feledje, hogy a fogyasztó numberOfConsumedElements értéke nulla.
6. Elem előállítása azonnali lejárattal
Amikor a Késleltetett üzenet getDelay () metódus negatív számot ad vissza, ez azt jelenti, hogy az adott elem már lejárt. Ebben a helyzetben a gyártó azonnal elfogyasztja ezt az elemet.
Negatív késleltetéssel tesztelhetjük az elem előállításának helyzetét:
int numberOfElementsToProduce = 1; int delayOfEachProducedMessageMilliseconds = -10_000; DelayQueueConsumer fogyasztó = new DelayQueueConsumer (sor, numberOfElementsToProduce); DelayQueueProducer producer = új DelayQueueProducer (sor, numberOfElementsToProduce, delayOfEachProducedMessageMilliseconds);
Amikor elkezdjük a tesztesetet, a fogyasztó azonnal elfogyasztja az elemet, mert már lejárt:
végrehajtó.beküldés (producer); végrehajtó.beküldés (fogyasztó); végrehajtó.awaitTermination (1, TimeUnit.SECONDS); végrehajtó.leállítás (); assertEquals (consumer.numberOfConsumedElements.get (), 1);
7. Következtetés
Ebben a cikkben a DelayQueue konstruálni a java.util.egyidejű csomag.
Megvalósítottuk a Késleltetett elem, amelyet a sorból állítottak elő és fogyasztottak el.
Kihasználtuk a DelayQueue lejárt elemeket fogyasztani.
Ezeknek a példáknak és kódrészleteknek a megvalósítása megtalálható a GitHub projektben - amely egy Maven projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.