Очередь блокировки - нужна дополнительная информация - PullRequest
5 голосов
/ 21 мая 2009

Этот вопрос связан с одним из моих предыдущих вопросов ..

Предыдущее сообщение

В них блокирующий характер упоминается как преимущество.

Я пытался разработать простой код для демонстрации природы блокировки, но я застрял. Я просто попытался сделать BlockingQueue размера 4 и попытался добавить 5 элементов, и в итоге получил java.lang.IllegalStateException. Может кто-нибудь показать мне пример кода для блокировки природы BlockingQueue?


public static void main(String[] args) {
    BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    try {
        bq.offer("A");
        bq.offer("B");
        bq.offer("C");
        bq.offer("D");
        bq.offer("E");

        System.out.println("1 = " + bq.take());
        System.out.println("2 = " + bq.take());
        System.out.println("3 = " + bq.take());
        System.out.println("4 = " + bq.take());
        System.out.println("5 = " + bq.take());
        System.out.println("6 = " + bq.take());
    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }
}

Я использовал этот сегмент кода. В этом случае я пытаюсь поместить 5 элементов в очередь размером 4. В этом случае 4 элемента (A, B, C, D) должны быть добавлены в очередь. Затем я вызываю метод take() во время печати. Разве «E» не вставляется автоматически в очередь, когда я звоню System.out.println("1 = " + bq.take());? Потому что он получает один свободный слот?

Ответы [ 4 ]

11 голосов
/ 21 мая 2009

Вы добавляли с add, offer или put? Я предполагаю, что вы использовали add, поскольку он единственный, кто может бросить IllegalStateException; но если вы прочитаете таблицу , вы увидите, что если вы хотите заблокировать семантику, вам следует использовать puttake для удаления ).

Редактировать: В вашем примере есть пара проблем.

Сначала я отвечу на вопрос "Почему E не вставляется, когда я звоню take() в первый раз?" Ответ заключается в том, что к тому времени, когда вы звоните take(), вы уже пытались и не смогли вставить E. После этого не будет ничего для вставки после освобождения места.

Теперь, если вы изменили offer() на put(), put("E") никогда не вернется. Зачем? Потому что он ждет какого-то другого потока , чтобы удалить элемент из очереди. Помните, BlockingQueues предназначены для доступа к нескольким потокам. Блокировка бесполезна (на самом деле хуже, чем бесполезна), если у вас однопоточное приложение.

Вот улучшенный пример:

public static void main(String[] args) {
    final BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    Runnable producer = new Runnable() {
        public void run() {
            try {
                bq.put("A");
                bq.put("B");
                bq.put("C");
                bq.put("D");
                bq.put("E");
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); 
            }
        }
    };
    Runnable consumer = new Runnable() {
        public void run() {
            try {
                System.out.println("1 = " + bq.take());
                System.out.println("2 = " + bq.take());
                System.out.println("3 = " + bq.take());
                System.out.println("4 = " + bq.take());
                System.out.println("5 = " + bq.take());
                System.out.println("6 = " + bq.take());
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    };
    new Thread(producer).start();
    new Thread(consumer).start();
}

Теперь вызов put("E") действительно будет успешным, поскольку теперь он может ожидать, пока поток потребителя не уберет "A" из очереди. Последний take() будет блокироваться бесконечно, поскольку шестой элемент не удаляется.

2 голосов
/ 21 мая 2009

ммайс избили меня до этого: P (+1)
это должно быть то, что вам нужно, удачи!

ПРИМЕЧАНИЕ. В вашем примере put () не удастся, потому что put () будет блокироваться, пока не будет доступно свободное место. Так как место никогда не доступно, программа никогда не продолжит выполнение.

==== старый ответ ======

BlockingQueue - это интерфейс, вам придется использовать один из реализующих классов.

«Блокирующая природа» просто утверждает, что вы можете запросить что-то из своей очереди, и если она пуста, поток, в котором она находится, будет блокировать (ждать), пока что-то не будет добавлено в очередь, а затем продолжить обработку.

ArrayBlockingQueue<br> DelayQueue<br> LinkedBlockingQueue<br> PriorityBlockingQueue<br> SynchronousQueue<br>

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
</p> <pre><code>//your main collection LinkedBlockingQueue<Integer> lbq = new LinkedBlockingQueue<Integer>(); //Add your values lbq.put(100); lbq.put(200); //take() will actually remove the first value from the collection, //or block if no value exists yet. //you will either have to interrupt the blocking, //or insert something into the queue for the program execution to continue int currVal = 0; try { currVal = lbq.take(); } catch (InterruptedException e) { e.printStackTrace(); }

1 голос
/ 21 мая 2009

Чтобы конкретно ответить на ваш вопрос: «Предложение» является неблокирующим вызовом предложения, поэтому в однопоточном методе, таком как тот, который вы опубликовали, вызов «предложение» («E») просто возвращает false, не изменяя полную очередь. Если вы используете вызов блокировки ('E'), он будет спать, пока не освободится место. Навсегда в вашем простом примере. Вам потребуется отдельный поток, считывающий очередь, чтобы создать место для завершения пут.

0 голосов
/ 24 мая 2016

Привет больше информации этот класс

 /**
 * Inserts the specified element into this queue if it is possible to do
 * so immediately without violating capacity restrictions, returning
 * {@code true} upon success and throwing an
 * {@code IllegalStateException} if no space is currently available.
 * When using a capacity-restricted queue, it is generally preferable to
 * use {@link #offer(Object) offer}.
 *
 * @param e the element to add
 * @return {@code true} (as specified by {@link Collection#add})
 * @throws IllegalStateException if the element cannot be added at this
 *         time due to capacity restrictions
 * @throws ClassCastException if the class of the specified element
 *         prevents it from being added to this queue
 * @throws NullPointerException if the specified element is null
 * @throws IllegalArgumentException if some property of the specified
 *         element prevents it from being added to this queue
 */
boolean add(E e);

/**
 * Inserts the specified element into this queue if it is possible to do
 * so immediately without violating capacity restrictions, returning
 * {@code true} upon success and {@code false} if no space is currently
 * available.  When using a capacity-restricted queue, this method is
 * generally preferable to {@link #add}, which can fail to insert an
 * element only by throwing an exception.
 *
 * @param e the element to add
 * @return {@code true} if the element was added to this queue, else
 *         {@code false}
 * @throws ClassCastException if the class of the specified element
 *         prevents it from being added to this queue
 * @throws NullPointerException if the specified element is null
 * @throws IllegalArgumentException if some property of the specified
 *         element prevents it from being added to this queue
 */
boolean offer(E e);

/**
 * Inserts the specified element into this queue, waiting if necessary
 * for space to become available.
 *
 * @param e the element to add
 * @throws InterruptedException if interrupted while waiting
 * @throws ClassCastException if the class of the specified element
 *         prevents it from being added to this queue
 * @throws NullPointerException if the specified element is null
 * @throws IllegalArgumentException if some property of the specified
 *         element prevents it from being added to this queue
 */
void put(E e) throws InterruptedException;

/**
 * Inserts the specified element into this queue, waiting up to the
 * specified wait time if necessary for space to become available.
 *
 * @param e the element to add
 * @param timeout how long to wait before giving up, in units of
 *        {@code unit}
 * @param unit a {@code TimeUnit} determining how to interpret the
 *        {@code timeout} parameter
 * @return {@code true} if successful, or {@code false} if
 *         the specified waiting time elapses before space is available
 * @throws InterruptedException if interrupted while waiting
 * @throws ClassCastException if the class of the specified element
 *         prevents it from being added to this queue
 * @throws NullPointerException if the specified element is null
 * @throws IllegalArgumentException if some property of the specified
 *         element prevents it from being added to this queue
 */
boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException;

/**
 * Retrieves and removes the head of this queue, waiting if necessary
 * until an element becomes available.
 *
 * @return the head of this queue
 * @throws InterruptedException if interrupted while waiting
 */
E take() throws InterruptedException;

/**
 * Retrieves and removes the head of this queue, waiting up to the
 * specified wait time if necessary for an element to become available.
 *
 * @param timeout how long to wait before giving up, in units of
 *        {@code unit}
 * @param unit a {@code TimeUnit} determining how to interpret the
 *        {@code timeout} parameter
 * @return the head of this queue, or {@code null} if the
 *         specified waiting time elapses before an element is available
 * @throws InterruptedException if interrupted while waiting
 */
E poll(long timeout, TimeUnit unit)
    throws InterruptedException;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...