如果已满,则从ArrayBlockingQueue中退出对象

时间:2016-12-08 09:58:12

标签: java multithreading guava blockingqueue

我正在使用ArrayBlockingQueue,但有时它会变满并阻止其他对象被添加到它。

我想要做的是删除队列中最旧的对象,然后在ArrayBlockingQueue满时添加另一个对象。我需要ArrayBlockingQueue像Guava EvictingQueue但线程安全。我打算扩展ArrayBlockingQueue并覆盖提供(E e)方法,如下所示:

public class MyArrayBlockingQueue<E> extends ArrayBlockingQueue<E> {

// Size of the queue
private int size;

// Constructor
public MyArrayBlockingQueue(int queueSize) {

    super(queueSize);
    this.size = queueSize;
}

@Override
synchronized public boolean offer(E e) {

    // Is queue full?
    if (super.size() == this.size) {
        // if queue is full remove element 
        this.remove();
    }
    return super.offer(e);
} }

上述方法可以吗?或者有更好的方法吗?

谢谢

2 个答案:

答案 0 :(得分:1)

您的MyArrayBlockingQueue不会覆盖BlockingQueue.offer(E, long, TimeUnit)BlockingQueue.poll(long, TImeUnit)。你真的需要一个队列&#34;阻止&#34;特征?如果不这样做,则可以使用EvictingQueue创建由Queues.synchronizedQueue(Queue)支持的线程安全队列:

Queues.synchronizedQueue(EvictingQueue.create(maxSize));

对于驱逐阻塞队列,我发现您提议的实施存在一些问题:

    如果队列为空,
  1. remove()可能会抛出异常。您的offer方法标有synchronized,但pollremove等不是这样,因此另一个线程可能会在调用size()和{ {1}}。我建议使用remove()而不是抛出异常。
  2. 您对poll()的调用可能仍会返回offer(即不是&#34;添加&#34;元素),因为另一种竞争条件是在检查大小和/或删除元素之间减小大小不同的线程添加一个填充队列的元素。我建议使用false结果的循环,直到返回offer为止(见下文)。
  3. 调用truesize()remove()都需要锁定,因此在最糟糕的情况下,您的代码会锁定并解锁3次(即使这样,它也可能无法按预期运行以前描述的问题)。
  4. 我相信以下实施将为您提供所需的信息:

    offer(E)

    请注意,如果在两次调用public class EvictingBlockingQueue<E> extends ArrayBlockingQueue<E> { public EvictingBlockingQueue(int capacity) { super(capacity); } @Override public boolean offer(E e) { while (!super.offer(e)) poll(); return true; } @Override public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { while (!super.offer(e, timeout, unit)) poll(); return true; } } 另一个线程之间移除元素,则此实现可能会不必要地删除元素。这似乎是我可以接受的,我并没有真正看到一个实用的方法(super.offer(E)是包私有的,ArrayBlockingQueue.lock是一个禁止的包,所以我们不能在那里放置一个实现访问和使用锁等。)。

答案 1 :(得分:0)

当你说“它变满并且阻止添加其他对象”时,这是否意味着确保可以随时添加对象就足够了?如果这是真的,您只需切换到无界队列,例如LinkedBlockingQueue。但请注意与ArrayBlockingQueue

相比的差异
  

链接队列通常比基于阵列的队列具有更高的吞吐量,但在大多数并发应用程序中具有较低的可预测性能。

您可以找到JDK队列实现的概述here