java - ArrayBlockingQueue 和添加 vs 放置 vs 容量

标签 java multithreading data-structures concurrency queue

来自 ArrayBlockingQueue 的 Javadoc ArrayBlockingQueue :

add

public boolean add(E e)

Inserts the specified element at the tail of this queue if it is possible 
to do so immediately without exceeding the queue's capacity, returning true 
upon success and throwing an IllegalStateException if this queue is full.

我总是这样解释这个语句(if is possible to do so immediately 部分)如下:

If the queue has free capacity, then the insert will succeed. If there is no empty space then it will not succeed.

但是这里我的理解是错误的。

在一个简单的例子中,我决定使用一个 ArrayBlockingQueue 20 个元素(小队列)并且有一个线程在做:

queue.take()

另一个线程没有通过 add 方法向队列添加元素,尽管队列几乎是空的。

我也通过调试验证了它。

一旦我将 queue.add(element) 的调用替换为 queue.put(element),该元素确实已添加到队列中。

那么这些方法有什么不同呢?

还有什么其他原因(除了容量)不能添加?


更新:

public class ConnectionListener implements Observer {

  public static BlockingQueue<ConnectionObject> queueConnections = new   ArrayBlockingQueue<ConnectionObject>(10);

  @Override
  public void update(Observable arg0, Object arg1) {
      ConnectionObject con = ((ConnectionObject)arg1);
      queueConnections.add(con);
  }

}  

ConnectionObject 只是 String 值的持有者。

public class ConnectionObject {
  private String user;  
  private String ip;
   //etc  
}

消费者:

public class ConnectionTreeUpdater extends Thread {  
  @Override
  public void run() {
    while(true){  
    try {  
    final ConnectionObject con = ConnectionListener.queueConnections.take();

如果我使用 add 不会抛出异常,但不会将元素添加到队列中。

只是一个想法:也许由于消费者在队列中“等待”,如果由于某些内部管理无法添加元素,则不会添加它并且不会抛出异常。可能是这种情况。

否则我无法理解为什么没有异常并且使用 put 代码可以工作。

putadd 的用法不同吗?

最佳答案

其实很简单:

  • 如果队列未满,两种方法都成功;
  • 如果队列已满,add()失败并出现异常 put() block 。

我认为文档在上面已经很清楚了。如果您不同意并希望获得第二意见,您可以检查 ArrayBlockingQueue 的源代码:

public boolean add(E e) {
    if (offer(e))
        return true;
    else
        throw new IllegalStateException("Queue full");
}

public boolean offer(E e) {
    if (e == null) throw new NullPointerException();
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        if (count == items.length)
            return false;
        else {
            insert(e);
            return true;
        }
    } finally {
        lock.unlock();
    }
}

public void put(E e) throws InterruptedException {
    if (e == null) throw new NullPointerException();
    final E[] items = this.items;
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        try {
            while (count == items.length)
                notFull.await();
        } catch (InterruptedException ie) {
            notFull.signal(); // propagate to non-interrupted thread
            throw ie;
        }
        insert(e);
    } finally {
        lock.unlock();
    }
}

关于java - ArrayBlockingQueue 和添加 vs 放置 vs 容量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7706666/

相关文章:

java - 使用 Jetty Websocket 客户端进行摘要式身份验证

java - 为什么这里要初始化ListNode两次呢?

java - 如何在 servlet 操作中同步请求

algorithm - 图、PRIM 和 DIJKSTRA 问题?

c++ - 用于随机访问和循环元素的最佳数据结构(C++)

java - AS400 Java Java 程序已完成,退出代码为 1

java - 寻找有关在 Intellij IDEA 9.x 中使用 JUnit 的教程

java - getDocumentContext() 上的 org.openntf.domino 异常

vb.net - VB.NET 中的 Me.Invoke 实际上并不是 "Invoke"- 线程在 Invoke 语句上停滞

c# - PLINQ遍历chunk分区的实现