ArrayBlockingQueue и добавление vs put vsacity - PullRequest
8 голосов
/ 10 октября 2011

Из Javadoc ArrayBlockingQueue 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 it is possible to do so immediattely) следующим образом:

Если очередь имеет свободную емкость, вставка будет выполнена успешно.Если нет пустого места, то это не удастся.

Но мое понимание здесь было неверным.

В простом случае, когда я решил использовать 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просто держатель для строковых значений.

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 код работает.

Разве put и add предназначены для использования по-разному?

Ответы [ 2 ]

15 голосов
/ 10 октября 2011

Это действительно очень просто:

  • если очередь не заполнена, оба метода завершаются успешно;
  • если очередь заполнена, add() завершается неудачно с исключением, тогда как put() блоков.

Я думаю, что документация достаточно ясна в отношении вышеизложенного. Если вы не согласны и хотели бы получить второе мнение, вы можете изучить исходный код для 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();
    }
}
4 голосов
/ 10 октября 2011

Одной из наиболее важных частей отладки проблемы является написание контрольного примера , чтобы убедиться, что то, что вы думаете, действительно происходит.Это либо подтверждает, либо опровергает вашу теорию.

Тестовый пример ниже показывает, что используемые вами методы ведут себя именно так, как указано в документации (которую вы цитируете):

public static void main(String[] args) {

    final ArrayBlockingQueue<Integer> myQueue =
            new ArrayBlockingQueue<Integer>(10);


    Thread t1 = new Thread(new Runnable() {

        public void run()
        {
            int i = 0;
            while (true)
            {
               try
                {
                    myQueue.add(i);
                    System.out.println("Added to queue! value: " + 
                                        i + 
                                        " size: " + myQueue.size());
                    i++;
                }
                catch (Exception e)
                {
                    System.out.println("add() threw exception, size: " +
                                        myQueue.size());
                    try
                    {
                        Thread.sleep(1000);
                    }
                    catch (InterruptedException ex)
                    {
                        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, 
                                                                   null, ex);
                    }
                }
            }
        }

    });

    Thread t2 = new Thread(new Runnable() {

        public void run()
        {
            while (true)
            {
                try
                {
                    Integer i = myQueue.take();
                    System.out.println("Took a off the queue! value: " + 
                                        i + 
                                       " size: " + myQueue.size());
                    Thread.sleep(100);
                }
                catch (InterruptedException ex)
                {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, 
                                                               null, ex);
                }
            }
        }
    });

    t1.start();
    t2.start();

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...