关于生产者 消费者问题
来源:互联网 发布:韩氏父子 圆号网络 编辑:程序博客网 时间:2024/05/21 22:32
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
这个阻塞队列就是用来给生产者和消费者解耦的。纵观大多数设计模式,都会找一个第三者出来进行解耦,如工厂模式的第三者是工厂类,模板模式的第三者是模板类。在学习一些设计模式的过程中,如果先找到这个模式的第三者,能帮助我们快速熟悉一个设计模式。
*生产者与消费者模型中,要保证以下几点:
1 同一时间内只能有一个生产者生产 生产方法加锁sychronized
2 同一时间内只能有一个消费者消费 消费方法加锁sychronized
3 生产者生产的同时消费者不能消费 生产方法加锁sychronized
4 消费者消费的同时生产者不能生产 消费方法加锁sychronized
5 共享空间空时消费者不能继续消费 消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行
6 共享空间满时生产者不能继续生产 生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行*“`
模型实例
/* * 商品类 */public class Good {int id;public Good(int id) {this.id = id;}public String toString(){return "good: "+ id;}}/* * 存放生产商品的容器类 * 生产者将生产的商品存放到这个类 * 消费者可以从这个类中消费商品 * 采用的是类似于栈的模型 */public class Box {Good[] good = new Good[6];int index = 0;/** * show 生产方法. * show 该方法为同步方法,持有方法锁; * show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费; * show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态, * show 等生产结束释放同步方法锁后消费才能持有该锁进行消费 * @param m 元素 * @return 没有返回值 */ public synchronized void push(Good goood){while(index == good.length){//判断商品是否存满try {this.wait();//商品存满进行等待,等待时会让出线程锁,让其他线程先执行} catch (InterruptedException e) {e.printStackTrace();}}this.notify();good[index] = goood;index ++;} /** * 消费方法 * 该方法为同步方法,持有方法锁 * 首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产; * 当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态 * 等消费结束释放同步方法锁后生产才能持有该锁进行生产 */public synchronized Good pop(){while(index == 0){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notify();index--;return good[index];}}/* * 生产者类 */public class Producer implements Runnable{Box box =new Box();public Producer(Box box) {this.box = box;}public void run() {for (int i = 0; i < 20; i++) {Good good = new Good(i);box.push(good);System.out.println("生产了: " +good);try {//每生产一个商品休眠一段时间Thread.sleep((int)(Math.random()*500));} catch (InterruptedException e) {e.printStackTrace();} }}}/* * 消费者类 */public class Consumer implements Runnable{Box box = new Box();public Consumer(Box box) {this.box = box;}public void run() {for (int i = 0; i < 20; i++) {Good good = box.pop();System.out.println("消费的商品是: "+ good);try {//每消费一个商品休眠一段时间Thread.sleep((int)(Math.random()*1000));} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} }}}/* * 测试类 */public class Test {public static void main(String[] args) {Box box =new Box();Producer p = new Producer(box);Consumer c = new Consumer(box);new Thread(p).start();new Thread(p).start();new Thread(c).start();}}
- 关于生产者-消费者问题
- 关于生产者-消费者问题
- 关于生产者-消费者问题
- 关于生产者 消费者问题
- 关于生产者消费者排序问题
- 关于生产者-消费者问题的一些思考
- 关于 生产者与 消费者问题 代码 ++ 注释
- 关于线程生产者和消费者的问题
- 操作系统中关于生产者消费者问题
- 生产者-消费者问题
- 生产者-消费者问题
- 生产者-消费者问题
- 操作系统:生产者-消费者问题
- 生产者与消费者问题
- 生产者-消费者问题
- java生产者 消费者问题
- 消费者和生产者问题
- 生产者消费者问题
- 各类解析漏洞汇总
- System Runtime 相关操作
- C/C++【知识点笔记】
- 子线程新建Handler为什么会报错?——浅谈Handler、Looper、Message关系
- 给定一个单链表,确认其是否为回文链表
- 关于生产者 消费者问题
- BMT硬件之ADC(一):转换参数——INL_DNL
- 页面置换算法
- Xpath的parent
- Linux系统中电源管理框架详解
- Android Camera 通过V4L2与kernel driver的完整交互过程
- 2016/8/31 求逆序数+约瑟夫杀人环问题
- MySQL 5.7 64位 Windows安装指南
- Po学校——考试一