博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
生产者消费者模型
阅读量:4550 次
发布时间:2019-06-08

本文共 2593 字,大约阅读时间需要 8 分钟。

生产者消费者模型:

为什么要使用生产者和消费者模式

在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。

什么是生产者消费者模式

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

这就像,在餐厅,厨师做好菜,不需要直接和客户交流,而是交给前台,而客户去饭菜也不需要不找厨师,直接去前台领取即可,这也是一个结耦的过程。

大白话: 厨师在生产包子的时候,假如一分钟做20个包子,但是吃包子的用户就一个人,吃不过来(产生浪费了),反过来,厨师一分钟做一个包子,吃包子的用户有20个(包子明显就不够吃了),就相当于20个子吃包子用户在大量等待,所以为了解决这种需求,需要加一个中间介质,这个中间介质来平衡两边的事情(也就是服务员,当然用包子蒸笼更加形象些,做好的包子放到蒸笼里面,用户需要购买的时候,从蒸笼里面拿就可以了,这个时候我们只需要维护着这个蒸笼里面有多少包子就行了,而且如果蒸笼满了,我就不需要在做了).这样就平衡了(解耦)

 

下面示例模仿生产消费者模型:

 

import time,random import queue,threading q = queue.Queue()     #这个就相当于中间介质 def Producer(name):       #生产包子   count = 0   while count <10:     print("making........")     time.sleep(random.randrange(3))       q.put(count)     print('Producer %s has produced %s baozi..' %(name, count))     count +=1     print("ok......") def Consumer(name):    #消费包子   count = 0   while count <10:     time.sleep(random.randrange(4))     if not q.empty():         data = q.get()         print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data))     else:         print("-----no baozi anymore----")     count +=1 #开4个线程去处理吃包子,这时候会打印20条no baozi anymore  因为只生产了10个包子 有3个线程去吃,每个线程吃10个包子 p1 = threading.Thread(target=Producer, args=('A',))   #线程1生产包子 c1 = threading.Thread(target=Consumer, args=('B',))   #线程2吃包子 c2 = threading.Thread(target=Consumer, args=('C',))  #线程3吃包子  c3 = threading.Thread(target=Consumer, args=('D',))   #线程4吃包子 p1.start() c1.start() c2.start() c3.start()

 

q.task_done() 和 q.join()示例
import time,random import queue,threading q = queue.Queue() def Producer(name):   count = 0   while count <10:     print("making........")     time.sleep(2)     q.put(count)     print('Producer %s has produced %s baozi..' %(name, count))     count +=1     q.task_done()   #这里面发送一个完成的信息给队里q   (q.join() )     print("ok......") def Consumer(name):   count = 0   while count <10:     q.join()        #这里面接收到队里q有完成的信息后,就接着运行下面代码,不然会一直在这卡死状态,等待上面生成完包子的信息(同理如果这是q.task_done(),就会产生吃完包子的消息,上面q.join()接收消息后接着生产)     data = q.get()     print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data))     count +=1 p1 = threading.Thread(target=Producer, args=('A',)) c1 = threading.Thread(target=Consumer, args=('B',)) c2 = threading.Thread(target=Consumer, args=('C',)) # c3 = threading.Thread(target=Consumer, args=('D',)) p1.start() c1.start() c2.start() # c3.start()

转载于:https://www.cnblogs.com/ajaxa/p/9134616.html

你可能感兴趣的文章
【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--请求处理结果适配篇(7/8)...
查看>>
CodeForces 731A Night at the Museum
查看>>
MySQL 删除数据库
查看>>
JavaScript 字符串(String) 对象
查看>>
How to use VisualSVN Server and TortoiseSVN to host your codes and control your codes' version
查看>>
微信小程序picker组件 - 省市二级联动
查看>>
Dynamics CRM 给视图配置安全角色
查看>>
Eclipse修改已存在的SVN地址
查看>>
C++ ACM基础
查看>>
(转)使用 python Matplotlib 库绘图
查看>>
进程/线程切换原则
查看>>
正则表达式语法
查看>>
20165301 2017-2018-2 《Java程序设计》第四周学习总结
查看>>
Vue的简单入门
查看>>
urllib 中的异常处理
查看>>
通过SQL Server的扩展事件来跟踪SQL语句在运行时,时间都消耗到哪儿了?
查看>>
SQL优化:重新编译存储过程和表
查看>>
PCB“有铅”工艺将何去何从?
查看>>
Solr环境搭建
查看>>
垂直居中的几种实现方法
查看>>