引言

生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区。其中一个是生产者,用于将消息放入缓冲区;另外一个是消费者,用于从缓冲区中取出消息。问题出现在当缓冲区已经满了,而此时生产者还想向其中放入一个新的数据项的情形,其解决方法是让生产者此时进行休眠,等待消费者从缓冲区中取走了一个或者多个数据后再去唤醒它。同样地,当缓冲区已经空了,而消费者还想去取消息,此时也可以让消费者进行休眠,等待生产者放入一个或者多个数据时再唤醒它。

生产者消费者模型

四个类

1.产品类:面包,饮料等

2.资源类(中介类):超市(买卖各种产品)

3.生产类(工厂类):生产各种产品

4.消费者类(顾客类):消费各种产品

代码:

1.产品类

package 设计模式之生产者消费者模式;

public class Bread {
private String brand;
private double price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Bread [brand=" + brand + ", price=" + price + "]";
}
public Bread(String brand, double price) {
super();
this.brand = brand;
this.price = price;
}
public Bread() {
super();
} }

2.中介类(资源类):超市

负责统筹安排所有资源,是生产者和消费者的桥梁。类似多线程中的共享资源,各个线程来操作同一个资源。

package 设计模式之生产者消费者模式;

public class Market {
//假设超市买面包的容量为6(即面包货架容量为6)
private Bread[] breads=new Bread[6];
int index=-1;// 为什么不默认为0 因为数组下标为0 是有一个数据的
//从工厂进面包
public synchronized void getBread(Bread bread){
//如果昨天生意不好,没有卖出面包,此时就不需要进货
if(index>=5){// 下标如果大于等于5 那就是有6个面包 工厂不需要生产 所以让工厂等着
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//生意很好,卖出了面包,需要进货
// 为了不覆盖任何面包 需要先加 下标 后赋值
index++;
//将进的面包放进数组里(货架上)
breads[index]=bread;
System.out.println("进了"+breads[index]);
//进货后,(通知)让顾客消费
this.notify();
}
// 卖面包
public synchronized void saleBread(){
//如果昨天生意很好,面包已经卖完了,那么顾客就需要等待
if(index<0){// 下标小于0 就证明是 数组中没有面包了 ,就让消费者等待
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//有面包可以卖
// 卖了哪个面包
System.out.println("[卖了]"+breads[index]);
// 卖完面包 下标自动减-
index--;
this.notify();
} }

3.工厂类

package 设计模式之生产者消费者模式;

public class Factory implements Runnable {
Market market; public Factory(Market market) {
super();
this.market = market;
}
@Override
public void run() {
for(int i=0;i<80;i++){
market.getBread(new Bread("桃李牌"+i, 4.5));
}
}
}

4.消费者

package 设计模式之生产者消费者模式;

public class Customer implements Runnable {
Market market;
public Customer(Market market){
this.market=market;
} @Override
public void run() {
for(int i=0;i<80;i++){
market.saleBread();
}
} }

测试类

package 设计模式之生产者消费者模式;

public class Test {
public static void main(String[] args){
Market market=new Market();
Factory factory=new Factory(market);
Customer customer=new Customer(market);
Thread thread=new Thread(factory,"生产者");
Thread thread2=new Thread(customer,"消费者");
thread.start();
thread2.start();
}
}

最新文章

  1. 如何把家里的pc改装成linux服务器
  2. java文件上传
  3. 安装rabbitmq
  4. 解决KDE桌面环境下Eclipse崩溃的问题--让Eclipse使用特定的GTK2主题运行
  5. 如何在IIS7或IIS7.5中导入导出站点及应用程序池.
  6. Linux内核启动
  7. tableView中自定header视图的重用问题
  8. HDU 5288 OO’s Sequence
  9. GitHub命令精简教程
  10. wxPython中按钮、文本控件的简单运用
  11. 文件属性和ls -lhi
  12. Unable to find a single main class from the following candidates ,显示有两个main class
  13. asp.net core cors中间件
  14. Spring MVC Controller异常处理总结
  15. selenium 初探
  16. 解决MySQL不允许远程连接的问题
  17. 在linux虚拟机上安装Docker
  18. mac系统下安装mysql 和phpmyadmin
  19. CSS(三):引入样式和优先级
  20. 学习TensorFlow的tf.concat使用

热门文章

  1. 需求收集实例 二 之 GF Phase 2
  2. DirectFB学习笔记四
  3. 03(1) Gaussians,GMMs基础
  4. 使用Asp.Net MVC开发兼职文章系统
  5. EverythingAboutJava
  6. linux中移动光标
  7. Markdown - 语法简介
  8. lxml简明教程
  9. 《JavaScript面向对象编程指南(第2版)》读书笔记(二)
  10. struts2标签库----控制标签详解