生产者消费者模式
生产者:指的是负责生产数据的模块。
消费者:指的是负责处理数据的模块。
消费者不能直接使用生产者的数据,它们之间有个“缓冲区”。生产者将生产好的数据放入“缓冲区”,消费者从“缓冲区”拿要处理的数据。
有了缓冲区以后,生产者线程只需要往缓冲区里面放置数据,而不需要管消费者消费的情况;同样,消费者只需要从缓冲区拿数据处理即可,也不需要管生产者生产的情况。生产者生产数据慢时,缓冲区仍有数据,不影响消费者消费;消费者处理数据慢时,生产者仍然可以继续往缓冲区里面放置数据 。
生产者消费者模式:
- 生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。
- 对于生产者,没有生产产品之前,消费者要进入等待状态。而生产了产品之后,又需要马上通知消费者消费。
- 对于消费者,在消费之后,要通知生产者已经消费结束,需要继续生产新产品以供消费。
代码实现一:
主方法测试类:
public class ProduceThread {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
new ShengChan(ss).start();
new XiaoFei(ss).start();
}
}
馒头类:
class ManTou {
private int id;
public ManTou(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
}
缓冲区类:
class SyncStack {
//定义存放馒头的盒子
private ManTou[] mt = new ManTou[10];
//定义操作盒子的索引
private int index;
/**
* 放馒头
*/
public synchronized void push(ManTou manTou) {
//判断盒子是否已满
while (this.index == this.mt.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//唤醒取馒头的线程
this.notify();
this.mt[this.index] = manTou;
this.index++;
}
/**
* 取馒头
*/
public synchronized ManTou pop() {
while (this.index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
this.index--;
return this.mt[this.index];
}
}
生产者类:
class ShengChan extends Thread {
private SyncStack ss;
public ShengChan(SyncStack ss) {
this.ss = ss;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("生产馒头:" + i);
ManTou manTou = new ManTou(i);
this.ss.push(manTou);
}
}
}
消费者类:
class XiaoFei extends Thread {
private SyncStack ss;
public XiaoFei(SyncStack ss) {
this.ss = ss;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
ManTou manTou = this.ss.pop();
System.out.println("消费馒头:" + i);
}
}
}
运行效果:
代码实现二:
商品类:
public class Goods {
private String name;//商品名称
private String brand;//商品品牌
private boolean isFlag;//用于标识是否有商品,true代表有商品,false代表没有商品
public Goods(String name, String brand) {
this.name = name;
this.brand = brand;
}
public Goods() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
//编写一个赋值的方法,同步监视为Goods类的对象
public synchronized void set(String name, String brand){
if (isFlag){//相当于isFile==true
try {
super.wait();//生产者线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}//当生产者线程被唤醒后,从wait()之后的代码开始执行
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setBrand(brand);
System.out.println("生产者生产了:"+this.getBrand()+this.getName());
//通知消费者
super.notify();
isFlag=true;
}
//编写一个取值的方法
public synchronized void get(){
if (!isFlag){
try {
super.wait();//消费者等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}//消费者线程被唤醒后,从wait()之后开始执行
System.out.println("消费者取走了:"+this.getBrand()+this.getName());
super.notify();//通知生产者线程
isFlag = false;//没有商品了
}
}
生产者类:
public class Producter implements Runnable{
private Goods goods;
public Producter(Goods goods){
this.goods = goods;
}
@Override
public void run() {
//生产商品
for (int i = 0;i<10;i++){
if (i%2!=0){//奇数
goods.set("小馒头","旺仔");//调用商品类的同步方法
}else{//偶数
goods.set("矿泉水","娃哈哈");
}
}
}
}
消费者类:
public class Customer implements Runnable{
private Goods goods;
public Customer(Goods goods){
this.goods=goods;
}
@Override
public void run() {
for (int i=0;i<10;i++){
goods.get();
}
}
}
主方法测试类:
public class Test {
public static void main(String[] args) {
//创建共享资源对象
Goods g = new Goods();
//创建生产者线程
Producter p = new Producter(g);
//创建消费者线程
Customer c = new Customer(g);
new Thread(p).start();
new Thread(c).start();
}
}
运行效果: