java中的DelayQueue - 未按预期工作

时间:2014-07-14 06:52:52

标签: java java.util.concurrent

我是并发编程的新手。我创建了两个类DelayedElement.java和DelayQueueExample来理解DelayQueue,如下所示:

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;

public class DelayQueueExample {
    public static void main(String[] args) throws InterruptedException {
        DelayQueue queue = new DelayQueue();
        Delayed element1 = new DelayedElement(5);
        queue.put(element1);
        System.out.println("Put done");
        Delayed element2 = queue.take();
        System.out.println("Take done");
        System.out.println(((DelayedElement)element2).getI());
    }
}

DelayedElement类如下:

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

public class DelayedElement implements Delayed {

    private int i;
    public DelayedElement(int i) {
        this.setI(i);
    }

    @Override
    public int compareTo(Delayed o) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = 10000l;
        return  unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

}

我运行程序,输出显示put已完成。但是当我调用queue.take()操作时,它会无限延迟。我在DelayedElement的getDeley方法中将延迟时间指定为10秒。那么为什么我的程序以这种方式运行?有人可以帮助我了解我的错误吗?

3 个答案:

答案 0 :(得分:1)

正如在DelayedQueue的java文档中所写的

  

元素的getDelay(TimeUnit.NANOSECONDS)发生过期   method返回小于或等于零的值。

您已重写getDelay(TimeUnit.NANOSECONDS)方法,以便始终返回常量延迟。你应该改变它,以便延迟随着时间的推移而减少。

这样的东西
// startTime is some future time set while creating delay element.
public long getDelay(TimeUnit unit) {
        long diff = startTime - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
}

答案 1 :(得分:0)

尝试以下面的方式实现set Delay()。 origin是将项目放入队列时的毫秒时间。

@Override
    public long getDelay( TimeUnit unit ) {
        return unit.convert( delay - ( System.currentTimeMillis() - origin ),
                TimeUnit.MILLISECONDS );
    }

答案 2 :(得分:0)

根据延迟接口的javadoc,getDelay(TimeUnit timeUnit)应该返回从元素添加到队列时的剩余延迟时间。

一种简单的方法是在元素添加到队列时设置到期时间(基于当前时间和dealy参数),并在调用getDelay方法时返回剩余时间到期时间。

实施可以是这样的

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

public class DelayedElement implements Delayed {
    private int i;
    /*
     * Expiry time in nano-seconds(more granular) 
     * i.e. time in nano seconds at which the element is added + delay converted to nanoseconds
     */
    private long expiryTime; 

    public DelayedElement(int i, int delay, TimeUnit dealyTimeUnit) {
        this.setI(i);
        expiryTime = TimeUnit.NANOSECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS) + TimeUnit.NANOSECONDS.convert(delay, dealyTimeUnit);
    }

    @Override
    public int compareTo(Delayed o) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public long getDelay(TimeUnit unit) {
           return  unit.convert((expiryTime- TimeUnit.NANOSECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS)), TimeUnit.NANOSECONDS);
    }

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }
}