Вы добавляли с add
, offer
или put
? Я предполагаю, что вы использовали add
, поскольку он единственный, кто может бросить IllegalStateException
; но если вы прочитаете таблицу , вы увидите, что если вы хотите заблокировать семантику, вам следует использовать put
(и take
для удаления ).
Редактировать: В вашем примере есть пара проблем.
Сначала я отвечу на вопрос "Почему 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()
будет блокироваться бесконечно, поскольку шестой элемент не удаляется.