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

生产者消费者问题
下面是我模拟生产者消费者问题的程序,可是怎么会发生死锁呢?wait不是会释放锁码?代码有点长,分给多一点
Java code

public class ProducerConsumer
{
    public static void main(String[] args)
    {
        Basket basket = new Basket(6);
        
        Producer p1 = new Producer(basket);
        Producer p2 = new Producer(basket);
        Consumer c1 = new Consumer(basket);
        Consumer c2 = new Consumer(basket);
        
        Thread t1 = new Thread(p1, "生产者1");
        Thread t2 = new Thread(p2, "生产者2");
        Thread t3 = new Thread(c1, "消费者1");
        Thread t4 = new Thread(c2, "消费者2");
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class Bread
{
    int id ;
    public Bread(int id)
    {
        this.id = id;
    }
}

class Basket
{
    int size;//当前面包数目
    int id;//当前面包id
    Bread[] breads;//存放面包的数组
    
    public Basket(int n)
    {
        breads = new Bread[n];
    }
}

class Producer implements Runnable
{
    Basket basket;//装面包的篮子
    boolean isGoOn = true;//是否继续生产
    
    /**
     * 构造方法,传递篮子
     */
    public Producer(Basket basket)
    {
        this.basket = basket;
    }
    
    /**
     * 重写run方法,当篮子不满的时候继续生产,
     * 满的时候wait
     */
    @Override
    public synchronized void run()
    {
        while (isGoOn)
        {
            try
            {
                Thread.sleep((int)(Math.random()*1000));
                
                if (basket.size < basket.breads.length)//篮子不满
                {
                    /*往当前篮子装面包,装完id和size分别加1*/
                    System.out.print(Thread.currentThread().getName()
                            + ": 生产的是" + basket.id  + "号面包,");
                    basket.breads[basket.size++] = new Bread(basket.id++);
                    System.out.println("现在共有" + basket.size + "个面包");
                    
                    /*篮子装的是第一个包子时,唤醒消费者*/
                    if (basket.size == 1)
                    {
                        System.out.println(Thread.currentThread().getName()
                                +" :有包子了,可以来吃了!");
                        this.notifyAll();
                    }
                }
                /*篮子满了,等待*/
                if (basket.size == basket.breads.length)
                {
                    System.out.println(Thread.currentThread().getName()
                                +" :篮子满了,请快点吃!");
                    wait();
                }
            }catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }    
    }
}

class Consumer implements Runnable
{
    Basket basket;//装面包的篮子
    boolean isGoOn = true;//是否继续消费
    
    /**
     * 构造方法,传递篮子
     */
    public Consumer(Basket basket)
    {
        this.basket = basket;
    }
    
    /**
     * 重写run方法,当篮子有面包时的时候可以消费,
     * 没有的时候wait
     */
    @Override
    public synchronized void run()
    {
        while (isGoOn)
        {
            try
            {
                Thread.sleep((int)(Math.random()*1000));
                
                if (basket.size > 0)//篮子不为空
                {
                    /*往当前篮子拿面包,拿的是id-1号面包,拿完size减1*/
                    System.out.print(Thread.currentThread().getName()
                            + ":拿的是" + --basket.id + "号面包,");
                    basket.size--;
                    System.out.println("现在还剩" + basket.size + "个面包");
                    
                    /*篮子拿的是最上面一个包子时,唤醒生产者*/
                    if (basket.size == basket.breads.length - 1)
                    {
                        System.out.println(Thread.currentThread().getName()
                                + ": 篮子有空位,可以继续生产了!");
                        this.notifyAll();
                    }
                }
                /*篮子为空,等待*/
                if (basket.size == 0)
                {
                    System.out.println(Thread.currentThread().getName()
                                + " :篮子空了,请快点生产!");
                    wait();    
                }    
            }catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }    
    }
}