什么是生产者/消费者模式?

某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模式。结构图如下:

生产者消费者模式有如下几个优点:

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

最新文章

  1. 记一道有意思的算法题Rotate Image(旋转图像)
  2. LVS
  3. POJ 3678 Katu Puzzle(强连通 法)
  4. 设计模式C#实现(四)——迭代器模式
  5. 史上最全的javascript知识点总结,浅显易懂。
  6. Oracle-单表合并列
  7. 在IT网站上少花些时间
  8. Framework 类库的事件编程
  9. Ubuntu14.04安装AMD显卡驱动双屏显示器完全解决方案
  10. [Spring入门学习笔记][静态资源]
  11. hdu 1226 BFS + bfs记录路径
  12. windows socket 网络编程
  13. java基础学习系列三
  14. [linux]孤儿进程与僵尸进程
  15. Pig store用法举例
  16. RocketMq2
  17. git push 推送大文件失败的处理办法
  18. django权限二(多级菜单的设计以及展示)
  19. .Net Framework 4.0: Using System.Lazy&lt;T&gt;
  20. android基本控件学习-----ToggleButton&amp;Switch

热门文章

  1. 【ASP.Net】 http请求中get,put,post,delete的区别与使用总结
  2. pgAdmin的数据恢复
  3. printf和cout的区别详述
  4. python测试
  5. 获得WebBrowser中的图片数据
  6. FreeCodeCamp---advanced Algorithm Scripting解法
  7. webpack优化记录
  8. Python 传递任意数量的实参
  9. 力扣(LeetCode) 20. 有效的括号
  10. 力扣(LeetCode) 27. 移除元素