为什么我的DelayQueue没有延迟并且打印顺序错误?

4

我有一个看似微不足道的简单演示DelayQueue的例子。

class DelayedThing implements Delayed {

    private final long waitUntil;
    private final String name;

    public DelayedThing(String name, long wait) {
        this.name = name;
        this.waitUntil = System.currentTimeMillis() + wait;
        System.out.println("DelayedThing(" + name + " wait=" + wait + " until-" + waitUntil);
    }

    @Override
    public long getDelay(TimeUnit unit) {
        System.out.println(name + " getDelay = " + unit.convert(waitUntil - System.currentTimeMillis(), TimeUnit.MILLISECONDS));
        return unit.convert(waitUntil - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        long diff = this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS);
        System.out.println(name + ".compareTo(" + o + ") = " + diff);
        return Long.signum(diff);
    }

    @Override
    public String toString() {
        return name;
    }
}

public void test() throws InterruptedException {
    BlockingQueue<Delayed> queue = new DelayQueue<>();
    queue.add(new DelayedThing("one second", 1000));
    queue.add(new DelayedThing("two seconds", 2000));
    queue.add(new DelayedThing("half second", 500));
    for (Delayed d : queue) {
        System.out.println(d);
    }
}

但是它会打印出来。
half second
two seconds
one second

显然是错误的。
1个回答

5
这是一个微妙的错误。我假设 DelayQueueiterator 会为每个元素执行一系列 take 调用。这是错误的!
请参阅 iterator() JavaDoc:

返回迭代器,其可遍历此队列中的所有元素(已过期和未过期)。

这相当出人意料。
正确的解决方法之一如下:
    while (queue.size() > 0) {
        System.out.println(queue.take());
    }

请注意,如果您尝试流式传输队列,也会出现此问题。
    queue.stream().forEach((d) -> {
        System.out.println(d);
    });

由于流式传输将在DelayQueue提供的iterator上进行,因此这也会产生意想不到的结果。


只有队列顶部的元素会被首先处理。+1 - Peter Lawrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接