为什么 ArrayBlockingQueue 在队列满的时候还没有被阻塞
Why ArrayBlockingQueue hasn't been blocked when the queue is full
我对 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,然后,producer往队列里放了4,现在队列应该满了,为什么producer还能往队列里放6,应该是blocked
producer: 6
在 consumer: 2
之前打印到您的控制台这一事实并不意味着 6
在 2
被删除之前添加。
如果您在添加和删除项目之前和之后打印队列的大小,您会发现它永远不会超过 3。
take/put 操作和打印不是原子的。
producer: 6
打印在consumer: 2
之前,并不代表生产者把6放在消费者消费2之前。
例如:
- 消费者执行queue.take(),取2
- 生产者执行queue.put(6)
- 制作人打印制作人:6
- 消费者pint消费者:2
我对 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,然后,producer往队列里放了4,现在队列应该满了,为什么producer还能往队列里放6,应该是blocked
producer: 6
在 consumer: 2
之前打印到您的控制台这一事实并不意味着 6
在 2
被删除之前添加。
如果您在添加和删除项目之前和之后打印队列的大小,您会发现它永远不会超过 3。
take/put 操作和打印不是原子的。
producer: 6
打印在consumer: 2
之前,并不代表生产者把6放在消费者消费2之前。
例如:
- 消费者执行queue.take(),取2
- 生产者执行queue.put(6)
- 制作人打印制作人:6
- 消费者pint消费者:2