消费者生产者错误中的意外输出

时间:2016-11-20 11:22:33

标签: java blockingqueue

我有一个代码,我试图运行它,它提供了未经检测的输出。

代码:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ProducerConsumerBlockingQueue {

    public static void main(String[] args) {
        Buffer buffer = new Buffer();

        ExecutorService executor = Executors.newFixedThreadPool(2);
        executor.execute(new ProdBlock(buffer));
        executor.execute(new ConsBlock(buffer));
        executor.shutdown();
    }

}
class ProdBlock implements Runnable{

    Buffer buffer;
    public ProdBlock(Buffer buffer) {
        this.buffer = buffer;
    }

    public void run() {
        for(int i = 1; i <= 10; i++){
            buffer.put(i);
        }

    }

}
class ConsBlock implements Runnable{

    Buffer buffer;
    ConsBlock(Buffer buffer){
        this.buffer = buffer;
    }
    public void run() {
        for(int i = 1; i <= 10; i++){
            buffer.get();
        }       
    }

}
class Buffer{
    int i;
    BlockingQueue<Integer> sharedObject = new ArrayBlockingQueue<Integer>(1);

    public void get(){
        try {
            System.out.println("Getting - " + sharedObject.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void put(int i){
        this.i = i;
        try {
            sharedObject.put(i);
            System.out.println("Putting - " + i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出:

Putting - 1
Putting - 2
Getting - 1
Putting - 3
Getting - 2
Getting - 3
Putting - 4
Putting - 5
Getting - 4
Getting - 5
Putting - 6
Getting - 6
Putting - 7
Putting - 8
Getting - 7
Getting - 8
Putting - 9
Putting - 10
Getting - 9
Getting - 10

预期输出:

Putting - 1
Getting - 1
Putting - 2
Getting - 2
Putting - 3
Getting - 3
Putting - 4
Getting - 4
Putting - 5
Getting - 5
Putting - 6
Getting - 6
Putting - 7
Getting - 7
Putting - 8
Getting - 8
Putting - 9
Getting - 9
Putting - 10
Getting - 10

正如所料,阻塞队列一次只能占用1个值,它是如何存储多个值的?

1 个答案:

答案 0 :(得分:1)

它没有存储多个值。它只是在take()方法返回后,生产者可以在队列中添加一个值并在另一个线程打印获取值之前打印它:

  1. producer thread:call put(1) - 队列有1个元素
  2. 制作人主题:打印&#34;放1&#34; - 队列有1个元素
  3. 消费者线程:调用take() - 队列为空
  4. 生产者线程:call put(2) - 队列有1个元素
  5. 制作人主题:打印&#34;放置2&#34; - 队列有1个元素
  6. 消费者线程:连接字符串&#34;获取 - &#34;使用在步骤3中获得的整数1,并打印结果 - 队列具有1个元素