线程——Java生产者消费者问题详解
2017-01-25 本文已影响138人
扒块腹肌
gghh######生产者消费者问题是操作系统中的经典问题,先用声明Thread子类的方法来实现
问题:
顾客去包子店中买包子
包子每次只能生产一个只能消费一个
包子有天津狗不理和无锡灌汤包两类,价格分别是20元和10元。
蒸笼中没有包子,店家才能生产,否则等待。
蒸笼中有包子,顾客才能消费,否则等待。
请实现此过程
首先要设计类
- 包子是生产者和消费者共有的,作为一类,包子的成员变量是其品牌,价格,存在状态,包子的存在状态需要更改,所以要有一个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. 运行结果
控制台输出.png