我是并发编程的新手。我创建了两个类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秒。那么为什么我的程序以这种方式运行?有人可以帮助我了解我的错误吗?
答案 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;
}
}