延迟队列(DelayQueue)带有容量限制

3

我正在使用 DelayQueue。我需要这样做是为了只有在延迟时间过去后才从队列中取出。我还想强制实施容量,就像 BlockingQueue 一样。我似乎找不到这个的 Collections 实现。是否存在这样的实现?如果不存在,最好的实现方式是什么?一种基本的方法是执行以下操作:

public void addSomethingToQueue(Object somethingToAdd){
    int capacity = 4;

    while(queue.size() >= capacity){
        try{
            wait();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }

    queue.add(somethingToAdd);
}

这意味着每次删除某些内容时都需要调用notify / notifyAll。这是一个相当小的类,所以这是可行的。但这听起来并不好。我也不确定wait / notify是否会导致更多问题?
是否更好地对DelayQueue进行子类化并修改其方法?这感觉有点不安全...
2个回答

3
为什么不组合使用BlockingQueueDelayQueue呢?例如:
class MyDelayBlockingQueue<T> implements Queue {
    private final DelayQueue<T> delayQ = ...
    private final BlockingQueue<T> blockingQ = ...

    public synchronized void offer(T obj) {
        blockingQ.offer(obj); // this will block if the Q is full
        delayQ.offer(obj);
    }

    public synchronized T poll() {
        T obj = delayQ.poll(); // This will handle the delay
        if (obj != null) {
            blockingQ.poll();
        }
        return obj;
    }

    // ...    
}

编辑

上面的代码会发生死锁。如果 Q 已满,offer 方法将在同步块中阻塞,所有未来调用 poll 的方法都将阻塞以获取 Q 的内部锁 - 导致死锁。尝试使用以下代码:

public class DelayBlockingQueue<E extends Delayed>
{
    private final DelayQueue<E> delayQ = new DelayQueue<E>();
    private final Semaphore available;

    public DelayBlockingQueue(int capacity)
    {
        available = new Semaphore(capacity, true);
    }

    public void offer(E e) throws InterruptedException
    {
        available.acquire();
        delayQ.offer(e);
    }

    public E poll()
    {
        E e = delayQ.poll();
        if (e != null)
        {
            available.release();
        }
        return e;
    }
}

看起来有点别扭,但可能比我最初想的要好。不过,采用这种方法,你需要覆盖很多方法(peek、take、poll、offer、add...)。 - Spycho
虽然这值得,但使用这个队列会更简单。 - Spycho
@Spycho,我最初发布的代码会出现死锁现象;我已经编辑了答案。 - Binil Thomas
谢谢。这似乎更合乎逻辑。 - Spycho
我分享了一个不同问题的实现。也许这就是你所需要的:https://dev59.com/vVXTa4cB1Zd3GeqPxwcp#48639437 - cWarren

0

1
抱歉,我应该进一步说明,DelayQueue 的延迟部分是必不可少的。LRUMap 没有这个功能。 - Spycho

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