Ú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.