I have a simple test for ArrayBlockingQueue as below:
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();
}
}
The result is:
producer: 2
producer: 0
producer: 1
consumer: 0
producer: 4
producer: 6
consumer: 2
etc...
my problem is, I have defined the size of ArrayBlockingQueue as 3, while the producer has put 2, 0 and 1, totally 3 items into the queue, and the queue is full now, then the consumer has consumed 0, the size of the queue should be 2 now, and then, the producer put 4 into the queue, the queue should be full now, why the producer can still put 6 into the queue, it's supposed to be blocked
The take/put action and the print are not atomic.
producer: 6
is printed before consumer: 2
, does not mean the producer put 6 before the consumer consume 2.
For example: