生产者消费者在java中使用队列

时间:2013-09-06 14:00:19

标签: java multithreading producer-consumer

我实现了生产者消费者问题,但我不知道为什么我的程序停止消费,即使生产者生产请帮助我找到bug并修复。

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class producerConsumer {
    private Queue<Integer> queue = new LinkedList<Integer>();
    private Random random = new Random();

    private synchronized void addData(int data) {
        while(queue.size()>=10) ;
        queue.add(data);
    }

    private synchronized int takeData() {
        while(queue.size()<=0) ;
        return queue.poll();
    }

    private void producer() {
        int data;
        while(true) {
            data=random.nextInt(100);
            addData(data);
            System.out.println("the producer produced :"+data);
        }
    }

    private void consumer() {
        try {
            while(true) {
                if(random.nextInt(10)==0) {
                    Thread.sleep(1000);
                    System.out.println("The consumed value:"+takeData()+";queue size is "+queue.size());
                }
            }
        }catch(InterruptedException e) {
        }
    }

    public static void main(String args[]) {
        producerConsumer pc = new producerConsumer();
        pc.process();
    }

    public void process() {

        Thread t1 = new Thread(new Runnable(){
            public void run() {
                producer();
            }
        });
        Thread t2 = new Thread(new Runnable(){
                public void run() {
                consumer();
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch(InterruptedException e) {
        }

    }
}

2 个答案:

答案 0 :(得分:4)

如果将while循环放在synchronized方法中,则使用者永远不会释放锁。在里面放一些wait()/ notify()逻辑。或者使用一些标准的同步队列实现。

以下情况应该更好:

private synchronized void addData(int data) {
    while(queue.size()>=10) wait(); //wait() will temporarily release lock
    queue.add(data);
    notifyAll();
}

private synchronized int takeData() {
    while(queue.size()<=0) wait(); //wait() will temporarily release lock
    int poll = queue.poll();
    notifyAll();
    return poll;
}

答案 1 :(得分:2)

@ greyfairer的答案看起来是正确的但是对于后代我建议你看看ExecutorService类,它们会为你处理大部分代码,包括作业排队和生产者之间的信号传递和消费者。您可能会将此作为练习,但如果没有,则为good tutorial

标准ExecutorService缺少的是限制未完成的工作数量,因此生产者不会通过排队太多工作来压倒内存。为此,您需要执行有界队列并使用RejectedExecutionHandler

有关详细信息,请参阅此答案:Process Large File for HTTP Calls in Java