Home > Java > Java DelayQueue test

Java DelayQueue test

DelayQueue Test

DelayQueue is a Java Queue that supports delaying for queue elements. An element inside the queue only taken after its expiration(delay) time.

Object class that inside the queue should implement the “Delayed” interface. This interface forces you to implement 2 methods:

getDelay,compareTo

getDelay method is important because Java decided to dequeue element from queue if getDelayed<=0 . For more information, visit Delayed Interface javadoc.

Lets start an example.

Firstly, you should define a class that represents the elements inside the queue. Our class name is NewString. This class has 2 important methods,getDelay and compareTo. If getDelay method returns 0 value or a value is lower than 0, this object will dequeue from the queue.

package com.turkcelltech.queuetests.DelayQueue;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class NewString implements Delayed{
private long endOfDelay;
private String text;
private long queueInsertTime;

public long getQueueInsertTime() {
return queueInsertTime;
}

public void setQueueInsertTime(long queueInsertTime) {
this.queueInsertTime = queueInsertTime;
}

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

public NewString()
{
}

public long getEndOfDelay() {
return endOfDelay;
}
public void setEndOfDelay(long endOfDelay) {
this.endOfDelay = endOfDelay;
}

@Override
public long getDelay(TimeUnit unit) {
// TODO Auto-generated method stub
long tmp = unit.convert((getQueueInsertTime()-System.currentTimeMillis())+endOfDelay, TimeUnit.MILLISECONDS);
return tmp;

}

@Override
public int compareTo(Delayed o) {
// TODO Auto-generated method stub
int ret = 0;
NewString ns = (NewString) o;

if ( this.endOfDelay < ns.endOfDelay ) ret = -1;
else if ( this.endOfDelay > ns.endOfDelay ) ret = 1;
else if ( this.getQueueInsertTime() == ns.getQueueInsertTime() ) ret = 0;

return ret;

}

}

And we are preparing Producer and Consumer classes. For each step in producer, a NewString object is creating and setting its attributes; for each step in consumer, consumer tries to take an element from the queue, if it could not, it waits until an element will be put (Refer the java queue documentation to understand differences between poll and take methods of queue, http://download.oracle.com/javase/1.5.0/docs/api/java/util/Queue.html )

Producer:

package com.turkcelltech.queuetests.DelayQueue;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.DelayQueue; 

public class Producer extends Thread {

private DelayQueue dq;
private SecureRandom random = new SecureRandom();

public Producer(DelayQueue dq) {
// TODO Auto-generated constructor stub
this.dq = dq;
}

@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
String str = getRandomString();
NewString nstr = new NewString();
int iRandom = 2000 + new Random().nextInt(1000);

nstr.setText(str);
nstr.setEndOfDelay(iRandom);
nstr.setQueueInsertTime(System.currentTimeMillis());
dq.put(nstr);

Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public String getRandomString() {
return new BigInteger(130, random).toString(32);
}

}

Consumer:

package com.turkcelltech.queuetests.DelayQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.LinkedBlockingQueue; 

public class Consumer extends Thread {

private DelayQueue dq;
private NewString ns;

public Consumer(DelayQueue dq) {
// TODO Auto-generated constructor stub
this.dq = dq;
}

@Override
public void run()
{
long dequeueTime = 0;
while ( true )
{
String str = null;
try {
ns = (NewString) dq.take();
dequeueTime = System.currentTimeMillis();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
StringBuffer sb = new StringBuffer();
sb.append(“——————–“+”\n”);
sb.append(“Queue Size ( Cons ) :”+dq.size()+”\n”);
sb.append(“Inserted Element :”+ns.getText()+”\n”);
sb.append(“Queue Insertion Time :”+ns.getQueueInsertTime()+”\n”);
sb.append(“Now ( dequeue time ) :”+dequeueTime+”\n”);
sb.append(“Expected Delay (ms):”+ns.getEndOfDelay()+”\n”);
sb.append(“Actual Delay (ms):”+(dequeueTime-ns.getQueueInsertTime())+”\n”);
sb.append(“Differences Actual and Expected Delay (ms):”+((dequeueTime-ns.getQueueInsertTime())-ns.getEndOfDelay())+”\n”);
sb.append(“——————–“+”\n”);
System.out.println(sb.toString());
//System.out.println(“Queue Size (Cons):”+dq.size()+”|Inserted Element:”+ns.getText()+”|Delay:”+ns.getEndOfDelay()+”|Queue Insertion Time:”+ns.getQueueInsertTime()+”|Now:”+System.currentTimeMillis());

}
}

}

And, create the main class that calls producer and consumer:

DelayQueueTest:

package com.turkcelltech.queuetests.DelayQueue;

import java.util.concurrent.DelayQueue;

public class DelayQueueTest {

private static DelayQueue dq;

public static void main(String args[])
{
System.out.println(“DelayQueue Example…”);
dq = new DelayQueue();
Producer p = new Producer(dq);
Consumer c = new Consumer(dq);
p.start();
c.start();

}
}

Lastly, run the DelayQueueTest.java, then lets analyse the output. After a
period of time, to find the elements that has expired become hard because the
queue size is increasing gradually because of in our example, producer is
faster than the consumer. I think this delay queing structure is great, useful and works well with middle-size queues but if the
queue size is big enough, deciding expired items much more hard.

——————–
Queue Size ( Cons ) :6190
Inserted Element :cqf44unuj7e54gm6ou8hafgt6b
Queue Insertion Time :1297351067151
Now ( dequeue time ) :1297351069152
Expected Delay (ms):2000
Actual Delay (ms):2001
Differences Actual and Expected Delay (ms):1
——————–

——————–
Queue Size ( Cons ) :6190
Inserted Element :q5a0atgilmik2jd6d3qu2bl2ic
Queue Insertion Time :1297351066479
Now ( dequeue time ) :1297351069152
Expected Delay (ms):2000
Actual Delay (ms):2673
Differences Actual and Expected Delay (ms):673
——————–

——————–
Queue Size ( Cons ) :6189
Inserted Element :oplb0ojmltu473jgbstbsdcauj
Queue Insertion Time :1297351065869
Now ( dequeue time ) :1297351069152
Expected Delay (ms):2001
Actual Delay (ms):3283
Differences Actual and Expected Delay (ms):1282
——————–

——————–
Queue Size ( Cons ) :6188
Inserted Element :la7uka3abq4t8ilbbki386dc2p
Queue Insertion Time :1297351065891
Now ( dequeue time ) :1297351069152
Expected Delay (ms):2001
Actual Delay (ms):3261
Differences Actual and Expected Delay (ms):1260
——————–

——————–
Queue Size ( Cons ) :6187
Inserted Element :35uesr3s7c8dbkrtfudjvg2tir
Queue Insertion Time :1297351066946
Now ( dequeue time ) :1297351069152
Expected Delay (ms):2001
Actual Delay (ms):2206
Differences Actual and Expected Delay (ms):205
——————–

——————–
Queue Size ( Cons ) :6186
Inserted Element :adcufi915fr0ehs43ebkl66apl
Queue Insertion Time :1297351063883
Now ( dequeue time ) :1297351069152
Expected Delay (ms):2002
Actual Delay (ms):5269
Differences Actual and Expected Delay (ms):3267
——————–

——————–
Queue Size ( Cons ) :8227
Inserted Element :sevfljifbd677h178l6t4225pp
Queue Insertion Time :1297351069243
Now ( dequeue time ) :1297351071244
Expected Delay (ms):2000
Actual Delay (ms):2001
Differences Actual and Expected Delay (ms):1
——————–

——————–
Queue Size ( Cons ) :8325
Inserted Element :unrvsodhafh02bcq21ords5ude
Queue Insertion Time :1297351069341
Now ( dequeue time ) :1297351071343
Expected Delay (ms):2001
Actual Delay (ms):2002
Differences Actual and Expected Delay (ms):1
……
……
……
Queue Size ( Cons ) :507047
Inserted Element :e4gjtvfq6b8hnlau27hlldvpve
Queue Insertion Time :1297350198016
Now ( dequeue time ) :1297350301063
Expected Delay (ms):2003
Actual Delay (ms):103047
Differences Actual and Expected Delay (ms):101044
——————–

——————–
Queue Size ( Cons ) :507046
Inserted Element :p8fe9d49o1ga0i9oe3ciepac37
Queue Insertion Time :1297350200057
Now ( dequeue time ) :1297350301063
Expected Delay (ms):2003
Actual Delay (ms):101006
Differences Actual and Expected Delay (ms):99003
——————–

——————–
Queue Size ( Cons ) :507045
Inserted Element :n5bd4saorqcmo3ahgfersfg4ns
Queue Insertion Time :1297350187489
Now ( dequeue time ) :1297350301063
Expected Delay (ms):2003
Actual Delay (ms):113574
Differences Actual and Expected Delay (ms):111571
——————–

——————–
Queue Size ( Cons ) :507044
Inserted Element :2522nr8jkk56qr3qbm06ie8er
Queue Insertion Time :1297350203764
Now ( dequeue time ) :1297350301063
Expected Delay (ms):2003
Actual Delay (ms):97299
Differences Actual and Expected Delay (ms):95296

Categories: Java Tags: ,
  1. John Martin
    March 14, 2011 at 10:09 pm

    Re: DelayQueue
    Firstly, thanks for the example – helped a great deal. Beware of using Milli secs. They can lead to odd results. e.g. at 1 second intervals put 3 entries on the Q with delays of 5000 millisecs at T0, 2000 at T1, and 1500 at T2. You would expect them to dequeue at times 3000 (1000+2000), 3500 (2000 + 1500), and 5000 (0+5000).
    They actually dequeue at 3500, 3500, 5000!. I have tried more complex combinations with similar results.
    I found the solution at http://www.devx.com/java/Article/21983/1954. The answer is to use nanosecs. I repeated my sequences that had failed and they all executed correctly. This may have affected your results, but I found it could be masked unless you looked at individual entries.
    Thanks
    John
    P.S. sorry about the lack of tags, I only do non-visual work.

  1. September 15, 2012 at 10:27 am

Leave a comment