引言

生产者-消费者(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();
}
}

Java中设计模式之生产者消费者模式-4的更多相关文章

  1. java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现

    java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了  wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样 ...

  2. 2.5多线程(Java学习笔记)生产者消费者模式

    一.什么是生产者消费者模式 生产者生产数据存放在缓冲区,消费者从缓冲区拿出数据处理. 可能大家会问这样有何好处? 1.解耦 由于有了缓冲区,生产者和消费者之间不直接依赖,耦合度降低,便于程序拓展和维护 ...

  3. 反应器模式 vs 生产者消费者模式

    相似点: 从结构上,反应器模式有点类似生产者消费者模式,即有一个或多个生产者将事件放入一个Queue中,而一个或多个消费者主动的从这个Queue中Poll事件来处理: 不同点: Reactor模式则并 ...

  4. JAVA多线程编程之生产者消费者模式

    Java中有一个BlockingQueue可以用来充当堵塞队列,下面是一个桌面搜索的设计 package net.jcip.examples; import java.io.File; import ...

  5. 多线程的设计模式--Future模式,Master-Worker模式,生产者-消费者模式

    代码示例: public interface Data { String getRequest(); } public class FutureData implements Data{ privat ...

  6. Java多线程-----实现生产者消费者模式的几种方式

       1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...

  7. .net学习之多线程、线程死锁、线程通信 生产者消费者模式、委托的简单使用、GDI(图形设计接口)常用的方法

    1.多线程简单使用(1)进程是不执行代码的,执行代码的是线程,一个进程默认有一个线程(2)线程默认情况下都是前台线程,要所有的前台线程退出以后程序才会退出,进程里默认的线程我们叫做主线程或者叫做UI线 ...

  8. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  9. java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】

    java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...

随机推荐

  1. How to trace the Geolocation of network traffic

    A case about suspicious malware App. A forensic examiner capatured some pcap files and he'd to know ...

  2. ArrayList和List主要区别 就是ArrayList类型不安全。

    什么是不安全? 1:List大家都知道初始化的时候需要定义其类型,例如 List<int> listTest = new List<int>():而ArrayList,例如:A ...

  3. List<T>对元素的查找。

    要在List<T>中查找特定的元素,可以使用Contains() .IndexOf().LastIndexOf()和BinarySearch()方法.除了 LastIndexOf()是从最 ...

  4. Unity CommandInvokationFailure: Failed to re-package resources. 解决方案

    在导入谷歌的SDK的时候,打包出来报错CommandInvokationFailure: Failed to re-package resources. 把Android SDK更新一下就轻松搞定了, ...

  5. phpcms后台管理

    phpcms从网上下载就好了,记住这个要安装在Wamp中的www文件下 从网页输入网址进入后台控制 输入密码账号,即进入后台控制界面: 后台管理有自带的网页模板把他换成自己的模板: 修改站点:   把 ...

  6. 系统启动 之 Linux系统启动概述(2)

    博客:http://blog.csdn.net/younger_china/article/details/51615916 Linu系统启动是一个"冗长乏味"的过程,那么我们现就 ...

  7. [UWP]了解模板化控件(9):UI指南

    1. 使用TemplateSettings统一外观 TemplateSettings提供一组只读属性,用于在新建ControlTemplate时使用这些约定的属性. 譬如,修改HeaderedCont ...

  8. java局部/成员/静态/实例变量

    局部变量和成员变量主要是他们作用域的区别成员变量个是类内部:局部变量是定义其的方法体内部(或者方法体内部的某一程序块内——大括号,主要看定义的位置).另外,成员变量可以不显式初始化,它们可以由系统设定 ...

  9. JAVA基础知识面试题

    一个JAVA文件可以定义多个类,但是只能有一个是public(也可以没有public类),并且该public的类的名称和JAVA文件名称相同.同时一个java文件可以有多个main方法,只有和java ...

  10. 适配器模式(Adpater Pattern)

    适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 适配器模式的用途 用电器做例子,笔记本电脑的插头一般都是三相的,即除了阳极.阴极 ...