DelayQueue 有对应的相反类吗?

4
我需要一个队列,能够自动删除早于给定毫秒数的元素 - 也就是说,我希望队列中的项目在一段时间后过期。
我发现有一个延迟队列似乎做了相反的事情:“只有在其延迟已过期时才可以取出元素。”(我从未使用过它)。
也许有一个队列实现可以满足我的需求?如果这个队列是有界的,那就更好了。
3个回答

2
这样做的问题在于,谁以及在什么时候会移除已过期的元素。如果你关心队列大小不会超过某个限制,你需要有一个单独的“清理”线程,在元素过期时将其从队列中移除。你可以使用DelayQueue实现它(offer会将元素添加到内部的LinkedHashSetDelayQueuepoll操作集合,另外一个清理线程则会轮询DelayQueue,并在元素“成熟”时将其从集合中移除)。
如果你不太关心元素被立即从队列中移除,你可以重写标准队列的poll方法,检查头部元素是否过期,如果过期,则清空队列的其余部分并返回null。

1
如果您想删除过期对象,需要一个DelayQueue和一个线程从中提取过期对象,类似于下面这样的内容:
static class Wrapper<E> implements Delayed {
    E target;
    long exp = System.currentTimeMillis() + 5000; // 5000 ms delay

    Wrapper(E target) {
        this.target = target;
    }

    E get() {
        return target;
    }

    @Override
    public int compareTo(Delayed o) {
        return 0;
    }

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


public static void main(String[] args) throws Exception {
    final DelayQueue<Wrapper<Integer>> q = new DelayQueue<>();
    q.add(new Wrapper<>(1));
    Thread.sleep(3000);
    q.add(new Wrapper<>(2));

    new Thread() {
        public void run() {
            try {
                for(;;) {
                    Wrapper<Integer> w = q.take();
                    System.out.println(w.get());
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };
    }.start();
}

如果我向队列中添加更多元素,这段代码就无法正常工作。q.add(new Wrapper<>(1)); Thread.sleep(1000); q.add(new Wrapper<>(2)); Thread.sleep(1000); q.add(new Wrapper<>(1)); Thread.sleep(1000); q.add(new Wrapper<>(2)); - Harsha

0

我猜这不是像Java那样的本地实现,但我不确定。但你可以使用缓存来处理这种情况,不确定是否是最好的方法,但你可以使用Google Guava来设置项目的过期时间,这样你只会获取未过期的值。

这里是Google Guava缓存实现的文档:Guava Doc

希望能对你有所帮助!


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