java设计模式之生产者/消费者模式
什么是生产者/消费者模式?
某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模式。结构图如下:
生产者消费者模式有如下几个优点:
1、解耦
由于有缓冲区的存在,生产者和消费者之间不直接依赖,耦合度降低。
2、支持并发
由于生产者与消费者是两个独立的并发体,他们之间是用缓冲区作为桥梁连接,生产者只需要往缓冲区里丢数据,就可以继续生产下一个数据,而消费者只需要从缓冲区了拿数据即可,这样就不会因为彼此的处理速度而发生阻塞。
3、支持忙闲不均
缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来 了。当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。 等生产者的制造速度慢下来,消费者再慢慢处理掉。
生产者-消费者模型准确说应该是“生产者-仓储-消费者”模型,这样的模型遵循如下的规则:
1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3、当消费者发现仓储没产品可消费时候会通知生产者生产。
4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费
此模型将要结合java.lang.Object的wait与notify、notifyAll方法来实现以上的需求。实例代码如下:
创建所谓的“仓库”,此类是(本质上:共同访问的)共享数据区域
//此类是(本质上:共同访问的)共享数据区域
public class SyncStack { private String[] str = new String[10]; private int index; //供生产者调用
public synchronized void push(String sst){
if(index == sst.length()){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.notify();//唤醒在此对象监视器上等待的单个线程
str[index] = sst;
index++;
} //供消费者调用
public synchronized String pop(){
if(index == 0){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.notify();
index--;
String product = str[index];
return product; } //就是定义一个返回值为数组的方法,返回的是一个String[]引用
public String[] pro(){
return str;
}
}
创建生产者:
public class Producter implements Runnable { private SyncStack stack; public Producter(SyncStack stack){
this.stack = stack;
} public void run(){
for(int i = 0;i<stack.pro().length;i++){
String producter = "产品" + i;
stack.push(producter);
System.out.println("生产了:" + producter);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}
}
创建消费者:
public class Consumer implements Runnable { private SyncStack stack; public Consumer(SyncStack stack){
this.stack = stack;
}
public void run(){
for(int i=0;i<stack.pro().length;i++){
String consumer = stack.pop();
System.out.println("消费了:" + consumer ); try {
Thread.sleep(400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
测试类:
public class TestDeam { public static void main(String[] args) {
SyncStack stack = new SyncStack();
Consumer p = new Consumer(stack);
Producter c = new Producter(stack); new Thread(p).start();
new Thread(c).start(); }
}
测试结果:
生产了:产品0
消费了:产品0
生产了:产品1
生产了:产品2
消费了:产品2
生产了:产品3
消费了:产品3
生产了:产品4
生产了:产品5
生产了:产品6
消费了:产品5
生产了:产品7
消费了:产品6
消费了:产品7
生产了:产品8
生产了:产品9
消费了:产品8
消费了:产品9
消费了:产品4
消费了:产品1
java设计模式之生产者/消费者模式的更多相关文章
- Java设计模式之生产者消费者模式
Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
- Java多线程-----实现生产者消费者模式的几种方式
1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...
- 【多线程】java多线程实现生产者消费者模式
思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...
- Java实现多线程生产者消费者模式的两种方法
生产者消费者模式:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据.生产者生产一个,消费者消费一个,不断循环. 第一种实现方法,用BlockingQueue阻塞队 ...
- Java多线程_生产者消费者模式2
在我的上一条博客中,已经介绍到了多线程的经典案列——生产者消费者模式,但是在上篇中用的是传统的麻烦的非阻塞队列实现的.在这篇博客中我将介绍另一种方式就是:用阻塞队列完成生产者消费者模式,可以使用多种阻 ...
- Java 并发编程 生产者消费者模式
本文部分摘自<Java 并发编程的艺术> 模式概述 在线程的世界里,生产者就是生产数据的线程,消费者就是消费数据的数据.生产者和消费者彼此之间不直接通信,而是通过阻塞队列进行通信,所以生产 ...
- Java多线程编程——生产者-消费者模式(1)
生产者-消费者模式在生活中非常常见.就拿我们去餐馆吃饭为例.我们会遇到以下两种情况: 1.厨师-客人 如下图所示,生产者.消费者直接进行交互. 生产者生产出产品后,通知消费者:消费者消费后,通知生产者 ...
- JAVA多线程之生产者 消费者模式 妈妈做面包案例
创建四个类 1.面包类 锅里只可以放10个面包 ---装面包的容器2.厨房 kitchen 生产面包 和消费面包 最多生产100个面包3.生产者4消费者5.测试类 多线程经典案例 import ja ...
随机推荐
- 使用Python制作第一个爬虫程序
用到的开发环境 IDE:pycharm python version :2.7 掌握的知识: Pycharm 还能更改Python的版本 代码如下:(重点就是 正则表达式的学习) # !/u ...
- 从命令行git转到Tortoise
阅读前请注意:本文先学命令行git的,但过不久遇到乱码问题久久不能解决,最后转向tgit. 2016-29 安装 next 下一步 设置目录 勾选需要的项: Additional icons是关于图标 ...
- 5、iptables之nat
iptables: 显式扩展.网络防火墙 显式扩展:multiport, iprange, string, time, connlimit, limit, state state:无关是哪种协议 /p ...
- SpringBoot war包部署到Tomcat服务器
(1)pom.xml文件修改<packaging>war</packaging>,默认是jar包,<build>节点中增加<finalName>spri ...
- for循环 Dictionary
Dictionary<string, string> dic = new Dictionary<string, string>(); dic.Add("1" ...
- 【Python】【有趣的模块】【Requests】无状态 & 无连接
无状态:原来的Web是静态,后来换成动态的就需要保存一些上下文信息,session和cookie应运而生 无连接:原来为了请求结束后赶紧把资源让出去,后来发现每次请求中有相同的小请求时候再重复执行(而 ...
- Codeforces 242 E. XOR on Segment
题目链接:http://codeforces.com/problemset/problem/242/E 线段树要求支持区间求和,区间内每一个数字异或上一个值. 既然是异或,考虑每一个节点维护一个长度为 ...
- 自定义 Git - 配置 Git
用git config配置 Git,要做的第一件事就是设置名字和邮箱地址: $ git config --global user.name "John Doe" $ git con ...
- 清除div重叠浮动的方法
在最后加入这样一个div. 并且为div加入以下属性: .clear { clear:both;}
- 力扣(LeetCode)202. 快乐数
编写一个算法来判断一个数是不是"快乐数". 一个"快乐数"定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 ...