Java生产者消费者问题详解

gghh######生产者消费者问题是操作系统中的经典问题,先用声明Thread子类的方法来实现

问题:

**顾客去包子店中买包子
包子每次只能生产一个只能消费一个
包子有天津狗不理和无锡灌汤包两类,价格分别是20元和10元。
蒸笼中没有包子,店家才能生产,否则等待。
蒸笼中有包子,顾客才能消费,否则等待。
请实现此过程**

Java生产者消费者问题详解_第1张图片

首先要设计类

  • 包子是生产者和消费者共有的,作为一类,包子的成员变量是其品牌,价格,存在状态,包子的存在状态需要更改,所以要有一个get和set方法
  • 生产者类:要有一个生产包子的方法,方法逻辑是有包子则等待,没包子才生产,生产完成了更改包子状态,通知消费者
  • 消费者类类:要有一个消费包子的方法,方法逻辑是有包子才消费,消费完成后更改包子状态,通知生产者继续生产包子
  • 一个测试类,创建包子对象,包子是共享数据,生产者消费者需要知道包子的具体状态,所以生产者消费者中需要有传入包子对象的构造方法

1. 先写包子类

/**
 * @author Joker
 */
public class BaoZi
{
    String name;
    int price;
    boolean flag = false;

//获取和设置包子的成员变量
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public int getPrice()
    {
        return price;
    }
    public void setPrice(int price)
    {
        this.price = price;
    }
    public boolean isFlag()
    {
        return flag;
    }
    public void setFlag(boolean flag)
    {
        this.flag = flag;
    }

    /**
     * 包子的有参构造方法,用于生产包子时创建相应品牌价格的包子对象
    */
    public BaoZi(String name, int price)
    {
        super();
        this.name = name;
        this.price = price;
    }

    /**
     * 包子的无参构造
     */
    public BaoZi()
    {
    }

      /**
      * 生产包子方法,用于生产者调用,同步线程声明synchronized 关键字
      * 包子有不同的品牌和价格,所以需要传入对应的成员变量值
      */
    public synchronized void produce(String name, int price)
    {
        if (flag)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }   

    //更改传递包子的属性 
        this.name = name;
        this.price = price; 

    //更改包子的状态并通知消费者
        flag = true;
        notify();
}

     /**
      * 消费包子方法,用于消费者调用,同步线程声明synchronized 关键字
      * 消费者只能消费生产者已经生产好的包子,所以无需更改包子的成员参数
      */
    public synchronized void consume()
    {
        if (!flag)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        //表明正在消费何种包子(必须是刚才生产者已经生产好的)
        System.out.println("正在消费" + getName() + ":" + getPrice() + "元");

          //更改包子存在状态并通知生产者继续生产
        flag = false;
        notify();
    }

}

2. 生产者类

public class Producer extends Thread
{
    BaoZi baoZi;
    /**
     * @param 构造方法接收包子对象进行通信
     */

    public Producer(BaoZi baoZi)
    {
        this.baoZi = baoZi;
    }

    @Override
    public void run()
    {
        super.run();
        // i计数来生产不同类型的包子,偶数次时生产天津狗不理
        int i = 0;
        while (true)
        {
            if (i % 2 == 0)
            {
                // 调用produce方法生产对应的包子并输出
                baoZi.produce("天津狗不理", 10);
                System.out.println("正在生产" + baoZi.getName() + ":" + baoZi.getPrice() + "元");
            }
            else
            {
                baoZi.produce("无锡灌汤包", 20);
                System.out.println("正在生产" + baoZi.getName() + ":" + baoZi.getPrice() + "元");
            }
            i++;
        }
    }
}

3. 消费者类

public class Consumer extends Thread
{
    BaoZi baoZi;
    /**
     * 构造方法 传入baozi对象进行通信
     */
    public Consumer(BaoZi baoZi2)
    {
        baoZi = baoZi2;
    }

    @Override
    public void run()
    {       
       super.run();
        while (true)
        {
            baoZi.consume();
        }
    }
}

4. 测试类

public class TestMain
{
    public static void main(String[] args)
    {
        Baozi baozi = new Baozi(null, 0);
        Producer producer = new Producer(baozi);
        Customer customer = new Customer(baozi);
               //启动线程
        producer.start();
        customer.start();
    }
}

5. 运行结果

Java生产者消费者问题详解_第2张图片

你可能感兴趣的:(JavaSe)