Почему ArrayBlockingQueue не был заблокирован, когда очередь заполнена
У меня есть простой тест для ArrayBlockingQueue, как показано ниже:
public class TestQueue {
static class Producer implements Runnable {
private ArrayBlockingQueue<Integer> queue;
private int index;
public Producer(ArrayBlockingQueue<Integer> queue, int index) {
this.queue = queue;
this.index = index;
}
@Override
public void run() {
try {
queue.put(index);
System.out.println("producer: " + index);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Consumer implements Runnable {
private ArrayBlockingQueue<Integer> queue;
public Consumer(ArrayBlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while(true) {
System.out.println("consumer: " + queue.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(3);
for (int i = 0; i < 10; i++) {
Producer producer = new Producer(queue, i);
new Thread(producer).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Consumer consumer = new Consumer(queue);
new Thread(consumer).start();
}
}
Результат:
producer: 2
producer: 0
producer: 1
consumer: 0
producer: 4
producer: 6
consumer: 2
etc...
моя проблема в том, что я определил размер ArrayBlockingQueue как 3, в то время как производитель поместил 2, 0 и 1, всего 3 элемента в очередь, и очередь сейчас заполнена, затем потребитель израсходовал 0, размер очередь должна быть 2, а затем, производитель вставил 4 в очередь, очередь должна быть заполнена сейчас, почему производитель все еще может поставить 6 в очередь, он должен быть заблокирован
2 ответа
Действие "взять / положить" и печать не являются атомарными.
producer: 6
печатается раньше consumer: 2
, не означает, что производитель поставил 6, прежде чем потребитель потребит 2.
Например:
- потребитель выполняет queue.take() и принимает 2
- производитель выполнить queue.put(6)
- производитель печать производитель: 6
- потребитель пинта потребитель: 2
Дело в том, что producer: 6
выводится на консоль раньше consumer: 2
, не значит что 6
добавлено до 2
устранен.
Если вы напечатаете размер очереди до и после добавления и удаления элементов, вы увидите, что он никогда не превышает 3.