java生产者消费者批量生产

时间:2016-06-27 10:51:33

标签: java multithreading producer-consumer

我在生产者 - 消费者面临问题。 我的要求是:

生产者一起生产100个对象并等待消费者消费。 然后消费者消耗这100个对象并等待生产者生产。 这个过程重复进行。

条件是,生产者不应该生成,直到对象大小为0, 在对象大小为100之前,消费者不应该消费。 即。 仅批量生产和消费。

class Producer extends Thread {
private Queue<Integer> queue;
private int maxSize;

public Producer(Queue<Integer> queue, int maxSize, String name) {
    super(name);
    this.queue = queue;
    this.maxSize = maxSize;
}

@Override
public void run() {
    while (true) {
        synchronized (queue) {
            while (queue.size() == maxSize) {
                try {
                    System.out.println("Queue is full, "
                            + "Producer thread waiting for "
                            + "consumer to take something from queue");
                    queue.wait();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            Random random = new Random();
            int i = random.nextInt();
            System.out.println("Producing value : " + i);
            queue.add(i);
            queue.notifyAll();
        }
    }
}

}

class Consumer extends Thread {
private Queue<Integer> queue;
private int maxSize;

public Consumer(Queue<Integer> queue, int maxSize, String name) {
    super(name);
    this.queue = queue;
    this.maxSize = maxSize;
}

@Override
public void run() {
    while (true) {
        synchronized (queue) {
            while (queue.isEmpty()) {
                System.out.println("Queue is empty,"
                        + "Consumer thread is waiting"
                        + " for producer thread to put something in queue");
                try {
                    queue.wait();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            System.out.println("Consuming value : " + queue.remove());
            queue.notifyAll();
        }
    }
}

}

public class ProdConsReference {
public static void main(String args[]) { 
    Queue<Integer> buffer = new LinkedList<Integer>(); 
    int maxSize = 10; 
    Thread producer = new Producer(buffer, maxSize, "PRODUCER"); 
    Thread consumer = new Consumer(buffer, maxSize, "CONSUMER"); 
    producer.start(); 
    consumer.start(); 
    }
}

输出:

      Queue is empty,Consumer thread is waiting for producer thread to put                             something in queue
      Producing value : 52648529
      Consuming value : 52648529
      Queue is empty,Consumer thread is waiting for producer thread to put something in queue
      Producing value : -2128028718
      Consuming value : -2128028718

任何人都可以指出我错过了什么。 提前致谢

2 个答案:

答案 0 :(得分:1)

我正在做一个练习,所以这是我的2美分:

每次添加/删除后,您都会通知其他线程。你不应该这样做。

您想要做的是:

制片:

  1. 检查队列是否为空。
  2. 如果是:生成100个项目(不是1个!),然后通知消费者,跳转到4个。
  3. 如果没有:等待收到通知
  4. 循环到1.(不是2!)
  5. 消费者:

    1. 检查队列是否已满。
    2. 如果是:使用直到队列为空,然后通知生产者。跳到4。
    3. 如果没有:等待收到通知
    4. 循环到1.(不是2!)
    5. 您可能想要使用Conditions

      如果这是练习/作业

      然后你应该看看zapl的方法,他在评论中说: 使用代表100个项目批次的列表队列。

      共享:有工作队列(线程安全数据结构,我建议使用阻塞)。

      制片人:

      • 获取批处理以及要处理的“任务”或项目的总数。我假设total可以被分割为batchsize。否则,你必须在制作时考虑到这一点。
      • 生产&lt; batchsize&gt;项目列表(=批处理)
      • 在workQueue
      • 中排队批次(项目列表)
      • 重复前2个步骤,直到达到总数。

      消费(或多个):

      • 从工作队列中获取批次(如果/尽快)
      • 批量处理所有项目

      请注意,如果您必须保留订单,则可以只使用一个消费者,或者额外努力强制对结果进行排序。

答案 1 :(得分:0)

Thnx对您的宝贵意见和建议。 我无法理解为什么不鼓励使用LinkedList。 在我的实时项目中,我的 productionCount 将超过数百万,而且我必须分批处理10000个。 以下链接也很有帮助。 How to know if other threads have finished?

这是我的实现仅使用2个线程。一个制片人&amp;其他主要线程本身作为消费者

            package threading;

            import java.util.LinkedList;
            import java.util.Queue;
            import java.util.Set;
            import java.util.concurrent.CopyOnWriteArraySet;


            public class ProdConsumerApp implements ThreadCompleteListener{
                boolean isProductionOver;
                public static void main(String args[]) {
                    ProdConsumerApp prodConsumerApp = new ProdConsumerApp();
                    prodConsumerApp.procudeAndConsume();
                }

                private void procudeAndConsume(){
                    Queue<Integer> buffer = new LinkedList<Integer>(); 
                    int maxSize = 100; 
                    int productionCount = 1000;

                    Producer producer = new Producer(buffer, maxSize, "PRODUCER", productionCount); 
                    producer.addListener(this);
                    producer.start(); 
                    consume(buffer);

                    System.out.println("Bye");
                }

                public void consume(Queue<Integer> queue){
                    while(!isProductionOver){//check whether production completed?
                        synchronized (queue) {
                            //when queue size is 0, notify and wait.
                            while(queue.isEmpty()){
                                try {
                                    queue.notify();
                                    queue.wait();
                                } catch (Exception ex) {
                                    ex.printStackTrace();
                                }
                            }
                            //consume until queue is empty.
                            while(!queue.isEmpty()){
                                System.out.println("Consuming value : " + queue.remove());
                            }
                        }
                    }
                }

                @Override
                public void notifyOfThreadComplete(Thread thread) {
                    System.out.println("notified");
                    isProductionOver = true;
                }

            }

            class Producer extends Thread {
                private Queue<Integer> queue;
                private int maxSize;
                private int productionCount;

                public Producer(Queue<Integer> queue, int maxSize, String name, int productionCount) {
                    super(name);
                    this.queue = queue;
                    this.maxSize = maxSize;
                    this.productionCount = productionCount;
                }

                private final Set<ThreadCompleteListener> listeners = new CopyOnWriteArraySet<ThreadCompleteListener>();

                public final void addListener(final ThreadCompleteListener listener) {
                    listeners.add(listener);
                }
                public final void removeListener(final ThreadCompleteListener listener) {
                    listeners.remove(listener);
                }
                private final void notifyListeners() {
                    for (ThreadCompleteListener listener : listeners) {
                        listener.notifyOfThreadComplete(this);
                    }
                }

                @Override
                public void run() {
                    synchronized (queue) {
                        for(int i=1;i<=productionCount;i++){
                            System.out.println("Producing value : " + i);
                            queue.add(i);

                            //when queue size is maxSize, notify and wait.
                            while(queue.size() == maxSize){
                                try {
                                    queue.notify();
                                    if(i==productionCount){
                                        //if last item is produced, notify listeners that production is completed.
                                        notifyListeners();
                                        //exit from while() and later for() and thereby terminating Producer.
                                        break;
                                    }
                                    queue.wait();
                                } catch (Exception ex) {
                                    ex.printStackTrace();
                                }
                            }
                        }           
                    }
                }

            }


            interface ThreadCompleteListener {
                void notifyOfThreadComplete(final Thread thread);
            }