日期:2014-05-20  浏览次数:20823 次

多线程之生产者消费者
Java code

package javase.thread;

import java.util.ArrayList;

public class ProducerConsumer {

    /**
     * @date: 2011-09-03 16:24
     * @desc:多线程中的经典问题-生产者消费者 如果多个线程使用同一个实现Runnable的类,那么他们共享该类的成员。
     */
    public static ArrayList store = new ArrayList();// 仓库
    public static void main(String[] args) {
        ProducerConsumer pc=new ProducerConsumer();
        ThreadTarget target0=pc.new ThreadTarget(0,store);//生产者
        ThreadTarget target1=pc.new ThreadTarget(1,store);//消费者
        for (int i=0;i<10;i++){
            Thread p=new Thread(target0);
            Thread c=new Thread(target1);
            p.setName("生产者"+i);
            c.setName("消费者"+i);
            p.start();
            c.start();
        }
    }

    class ThreadTarget implements Runnable{
        public  ArrayList productsList = null;
        private int flag=0;//0为生产者,1为消费者
        public ThreadTarget(int flag,ArrayList st){
            this.flag=flag;
            this.productsList=st;
        }
        public void run() {
            if (this.flag==0){
                produce();
            }
            else{
                consume();
            }
        }
        public synchronized void consume() {
            while(productsList.size()==0) {
                try {
                    System.out.println("产品库为空," + Thread.currentThread().getName() + "需要等待");
                    Thread.currentThread().wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            productsList.remove(0);
            System.out.println(Thread.currentThread().getName() + "消费了一个产品。产品库存为:" + productsList.size());
            try{
                this.notifyAll();//通知生产者可以进行生产了。
            }
            catch(IllegalMonitorStateException e){
                
            }
        }
        public synchronized void produce() {
            while(productsList.size() == 20) {
                try {
                    System.out.println("产品库已满," + Thread.currentThread().getName() + "需要等待");
                    Thread.currentThread().wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }// 产品到20了。 
            productsList.add("p");//p即product的代表。
            System.out.println(Thread.currentThread().getName() + "生产了一个产品。产品库存为:" +productsList.size());
            this.notifyAll();//通知消费者线程可以进入队列等候jvm分配cpu时间片了。
            
        }
    }
}


注:我机器jdk为1.6。
此程序有时运行结果完全正确,有时会出现IllegalMonitorException,我仔细查看代码,实在看不出什么玄机。还忘行家指点迷津。此外还有个问题,本例中如果其中的一个线程,如生产者线程运行时执行run方法,在run中调用了produce,这个produce方法就几行代码,会很快执行完毕,理论上可能存在produce方法执行到一半或部分时被jvm调度中断么?


------解决方案--------------------
你的生产者和消费者没有共享资源。你是new了两个ThreadTarget对象。
------解决方案--------------------
上锁的资源和等待的不一致造成的。
Thread.currentThread().wait()改成this.wait()或 productsList.wait();