Aarish Ramesh
Aarish Ramesh

Reputation: 7043

Polling after a delay in delayed queue

I have a sample program from which i am trying to understand delayed queue. I offer person objects to the queue with the a particular delay and when i try polling the objects after an interval of 5 seconds, I am supposed to get all the objects for which the delay has expired until then. But instead I get null for which i don't understand the reason. But this polling works when i set the delay to 0. Can someone please help me figure where am i making mistake in the sample code below?

public class DelayedQueue {
    public static void main(String[] args) {
        BlockingQueue<Person> queue = new DelayQueue<Person>();
        Person a = new Person("ram", "chennai", 1);
        Person b = new Person("nick", "manali", 1);
        Person c = new Person("sam", "delhi", 2);
        try {
            queue.offer(a);
            queue.offer(b);
            queue.offer(c);
            System.out.println(queue.poll(5, TimeUnit.SECONDS));
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
}

class Person implements Delayed {
    private String name;
    private String place;
    private int runningTime;

    public Person(String name, String place, int runningTime) {
        this.name = name;
        this.place = place;
        this.runningTime = runningTime;
    }
    public long getDelay(TimeUnit timeUnit) {           
        return timeUnit.convert(this.runningTime, TimeUnit.MILLISECONDS);

    @Override
    public int compareTo(Delayed person) {
        Person b = (Person)person;   
        return this.name.compareTo(b.name);
    }

    @Override
    public long getDelay(TimeUnit timeUnit) {           
        return timeUnit.convert(this.runningTime, TimeUnit.MILLISECONDS);
    }
}

Upvotes: 1

Views: 1805

Answers (1)

Maas
Maas

Reputation: 1357

Your getDelay implementation is wrong

@Override
    public long getDelay(TimeUnit timeUnit) {       
        **// This will never return zero! and the element is never available.**
        return timeUnit.convert(this.runningTime, TimeUnit.MILLISECONDS);
    }

Try to do something like this

@Override
    public long getDelay(TimeUnit timeUnit) {           
        return timeUnit.convert(endOfDelay - System.currentTimeMillis(),
                          TimeUnit.MILLISECONDS);
    }

Where endOfDelay is set as long ( System.currentTimeMillis() + delay (in ms)

Here is the working piece of your code:

public class DelayedQueue
{
    public static void main(String[] args)
    {
        BlockingQueue<Person> queue = new DelayQueue<Person>();
        Person a = new Person("ram", "chennai", 1);
        Person b = new Person("nick", "manali", 1);
        Person c = new Person("sam", "delhi", 2);
        try
        {
            queue.offer(a);
            queue.offer(b);
            queue.offer(c);
            System.out.println(queue.poll(2, TimeUnit.SECONDS));
        } catch (InterruptedException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
}
class Person implements Delayed
{
    private String name;
    private String place;
    private long delayTime;

    public Person(String name, String place, long delayTime)
    {
        this.name = name;
        this.place = place;
        this.delayTime = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(delayTime);
    }

    @Override
    public int compareTo(Delayed person)
    {
        Person b = (Person) person;
        return this.name.compareTo(b.name);
    }

    @Override
    public long getDelay(TimeUnit timeUnit)
    {
        return timeUnit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }
}

Upvotes: 2

Related Questions