今天打算来介绍一下“生产者/消费者模式”,这玩意儿在很多开发领域都能派上用场。由于该模式很重要,打算分几个帖子来介绍。今天这个帖子先来扫盲一把。如果你对这个模式已经比较了解,请跳过本帖子,直接看下一个帖子(关于如何确定数据单元)
。
<!-- program-think-->
看到这里,可能有同学心中犯嘀咕了:在四人帮(GOF)的23种模式里面似乎没听说过这种嘛!其实GOF那经典的23种模式主要是基于OO的(从书名
《Design Patterns: Elements of Reusable Object-Oriented
Software》就可以看出来)。而Pattern实际上即可以是OO的Pattern,也可以是非OO的Pattern的。
★简介
言归正传!在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块
是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者
;而处理数据的模块,就称为消费者
。
单单抽象出生产者和消费者,还够不上是生产者/消费者模式。该模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介。生产者把数据放入缓冲区,而消费者从缓冲区取出数据。大概的结构如下图。
为了不至于太抽象,我们举一个寄信的例子(虽说这年头寄信已经不时兴,但这个例子还是比较贴切的)。假设你要寄一封平信,大致过程如下:
1、你把信写好——相当于生产者制造数据
2、你把信放入邮筒——相当于生产者把数据放入缓冲区
3、邮递员把信从邮筒取出——相当于消费者把数据取出缓冲区
4、邮递员把信拿去邮局做相应的处理——相当于消费者处理数据
★优点
可能有同学会问了:这个缓冲区有什么用捏?为什么不让生产者直接调用消费者的某个函数,直接把数据传递过去?搞出这么一个缓冲区作甚?
其实这里面是大有讲究的,大概有如下一些好处。
◇解耦
假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。将来如果消费者的代码发生变化,可能会影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合也就相应降低了。
接着上述的例子,如果不使用邮筒(也就是缓冲区),你必须得把信直接交给邮递员。有同学会说,直接给邮递员不是挺简单的嘛?其实不简单,你必须得认识谁
是邮递员,才能把信给他(光凭身上穿的制服,万一有人假冒,就惨了)。这就产生和你和邮递员之间的依赖(相当于生产者和消费者的强
耦合)。万一哪天邮递员换人了,你还要重新认识一下(相当于消费者变化导致修改生产者代码)。而邮筒相对来说比较固定,你依赖它的成本就比较低(相当于和缓冲区之间的弱
耦合)。
◇支持并发(concurrency)
生产者直接调用消费者的某个方法,还有另一个弊端。由于函数调用是同步的(或者叫阻塞的),在消费者的方法没有返回之前,生产者只好一直等在那边。万一消费者处理数据很慢,生产者就会白白糟蹋大好时光。
使用了生产者/消费者模式之后,生产者和消费者可以是两个独立的并发主体(常见并发类型有进程和线程两种,后面的帖子会讲两种并发类型下的应用)。生产者把制造出来的数据往缓冲区一丢,就可以再去生产下一个数据。基本上不用依赖消费者的处理速度。
其实当初这个模式,主要就是用来处理并发问题的。
从寄信的例子来看。如果没有邮筒,你得拿着信傻站在路口等邮递员过来收(相当于生产者阻塞);又或者邮递员得挨家挨户问,谁要寄信(相当于消费者轮询)。不管是哪种方法,都挺土的。
◇支持忙闲不均
缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。等生产者的制造速度慢下来,消费者再慢慢处理掉。
为了充分复用,我们再拿寄信的例子来说事。假设邮递员一次只能带走1000封信。万一某次碰上情人节(也可能是圣诞节)送贺卡,需要寄出去的信超过1000封,这时候邮筒这个缓冲区就派上用场了。邮递员把来不及带走的信暂存在邮筒中,等下次过来时再拿走。
费了这么多口水,希望原先不太了解生产者/消费者模式的同学能够明白它是怎么一回事。然后在下一个帖子中,我们来说说如何确定数据单元
。
另外,为了方便阅读,把本系列帖子的目录整理如下:
1、如何确定数据单元
2、队列缓冲区
3、环形缓冲区
4、双缓冲区
5、......
分享到:
相关推荐
在算法开发中,首先要理解粒子滤波的工作原理。这一过程通常包括一个大循环,循环中包括对数学概念的实验和结果的展示。这个实验循环通常包含几个关键步骤,如算法介绍、样本程序回顾、预测和测量方法的探讨、数据...
连接池 JAVA 数据库 很好理解 你只需要 读一下你的 配置文件 就可以了
超好的快速幂算法详解.7z超好的快速幂算法详解.7z超好的快速幂算法详解.7z超好的快速幂算法详解.7z超好的快速幂算法详解.7z超好的快速幂算法详解.7z超好的快速幂算法详解.7z超好的快速幂算法详解.7z超好的快速幂算法...
`tree.gif`可能是一个图像文件,用于表示Perl语法结构或者程序流程图,帮助学习者更好地理解复杂的概念。 `func.htm`可能包含Perl函数的参考指南,列出常用的内置函数和它们的用法。Perl有丰富的内置函数库,如`...
"超好PPT各方面教程精选"这个压缩包文件提供了丰富的资源,涵盖了从设计美观的模板到掌握核心制作技巧的多个方面。下面将详细解析每个文件所包含的知识点。 1. **PPT打造iPhone图标.ppt**: 这个教程可能介绍了...
这类产品体积小、便于携带,且消费者在选购时更倾向于通过网络比价,因此在线销售成为这类产品的最佳销售方式之一。 为了更详尽地指导读者成功开设和运营网店,《超好的网上开店知识全书》还涵盖了行业选择、货源...
Spring框架是Java企业级应用开发中的重要组成部分,它以其模块化、灵活性...总的来说,这份"超好的Spring学习资料"将带你深入理解Spring框架,无论你是初学者还是经验丰富的开发者,都能从中受益,提高自己的技术水平。
数据库是信息技术领域中不可或缺的一部分,尤其对于初学者来说,理解并掌握数据库的基础至关重要。本教程旨在为初学者提供一个全面的数据库学习指南,让你能够快速入门并深入理解数据库的核心概念。 1. 数据库基本...
《VC超好的教程》是一本面向初学者的VC++学习资源,特别适合那些希望进入编程世界的新人。"Visual+C+++从入门到精通最新完整清晰版.pdf"是这个压缩包中的核心文件,它提供了全面且易懂的教学内容,帮助读者逐步掌握...
这个“国外高手些的超好的MES系统源码”无疑为开发者和研究者提供了一个宝贵的参考资料。 首先,我们要理解MES系统的核心功能。MES系统主要负责计划调度、生产监控、质量管理、设备管理和物料跟踪等,它连接了ERP...
标题中的“超好的渲染软件”指的是高质量的计算机图形学渲染工具,这类软件能够将3D模型、场景或设计转化为逼真的图像或动画。在IT领域,渲染是制作虚拟现实、建筑可视化、产品设计、电影特效等领域不可或缺的一环。...
浏览器超好
超好的 表白源码
2. **可定制性**:开发者可以根据项目需求调整样式、功能和行为,如自定义颜色方案、显示模式(单月、多月、年视图)以及是否支持时间选择。 3. **响应式设计**:适应不同设备的屏幕大小,如手机、平板电脑和桌面...
HSV模式则更易于理解,通过调整色调、饱和度和亮度可以直观地创建和编辑颜色。取色板工具通常会提供色轮、调色盘等多种界面,让设计师能直观地选取和混搭颜色。 此外,"千宇取色板"可能具备以下特性: 1. **色彩...
JavaScript是一种广泛应用于网页和网络应用开发的脚本语言,它主要负责处理客户端的交互和动态内容。...通过理解并掌握这些知识点,开发者可以构建出功能丰富的交互式日历组件,满足用户的多种需求。
《Hibernate_PDF_超好》是一份集合了深入学习Hibernate框架的重要资料,包含三本PDF电子书和一个配置文件。Hibernate作为Java世界中著名的对象关系映射(ORM)框架,它极大地简化了数据库操作,使得开发者可以专注于...
这个名为"学习ARM的绝版超好资料"的压缩包,显然是为那些想要深入理解并掌握ARM技术的学习者准备的宝贵资源。描述中提到的"现成"和"适合初学者"表明,这份资料可能包含了从基础到进阶的全方位教程,旨在帮助新手快速...
2. **求职意向**:明确表述你所申请的职位,以及你对该职位的理解和期待。模板可能已有预设的空间或提示,帮助你准确表达。 3. **教育背景**:列出你的学历、专业及毕业院校。如果成绩优异,可以适当提及GPA或排名...