【问题标题】:DelayQueue with capacity有容量的延迟队列
【发布时间】:2011-07-19 11:45:23
【问题描述】:

我正在使用延迟队列。我需要使用它以便仅在延迟过去时从队列中取出。我还想强制执行容量,就像 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。这是一个相当小的班级,所以这是可行的。不过听起来不太好。而且我不确定等待/通知是否会导致进一步的问题?

将 DelayQueue 子类化并弄乱它的方法会更好吗?感觉有点坑爹……

【问题讨论】:

    标签: java collections concurrency


    【解决方案1】:

    为什么不编写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 我贴的原代码会死锁;我已经编辑了答案。
    • 谢谢。这似乎也更合乎逻辑。
    • 我为另一个问题分享了一个实现。也许这就是你的意思:stackoverflow.com/a/48639437/895732
    【解决方案2】:

    您可以使用 LRU: http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used

    来自 Apache Commons 的示例实现: http://commons.apache.org/collections/api/org/apache/commons/collections/LRUMap.html

    所以你不要再写这个了;-)

    【讨论】:

    • 对不起,我应该进一步说明,DelayQueue 的延迟部分是必不可少的。 LRUMap 不这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 2013-09-27
    • 2023-03-03
    • 1970-01-01
    • 2015-09-30
    • 2014-06-10
    相关资源
    最近更新 更多