python多进程下的生产者和消费者模型


Posted in Python onMay 07, 2020

一、生产者消费者模型介绍

1.1 为什么需要使用生产者消费者模型

生产者是指生产数据的任务,消费者是指消费数据的任务。当生产者的生产能力远大于消费者的消费能力,生产者就需要等消费者消费完才能继续生产新的数据,同理,如果消费者的消费能力远大于生产者的生产能力,消费者就需要等生产者生产完数据才能继续消费,这种等待会造成效率的低下,为了解决这种问题就引入了生产者消费者模型。

1.2 如何实现生产者消费者模型

进程间引入队列可以实现生产者消费者模型,通过使用队列无需考虑锁的概念,因为进程间的通信是通过队列来实现的;

生产者生产的数据往队列里面写,消费者消费数据直接从队列里面取,这样就对实现了生产者和消费者之间的解耦。

生产者 -- >  队列  <--消费者

二、Queue实现生产者消费者模型

2.1 消费者生产者模型代码

from multiprocessing import Process, Queue
import time
 
# 消费者方法
def consumer(q, name):
  while True:
    res = q.get()
    # if res is None: break
    print("%s 吃了 %s" % (name, res))
 
# 生产者方法
def producer(q, name, food):
  for i in range(3):
    time.sleep(1) # 模拟生产西瓜的时间延迟
    res = "%s %s" % (food, i)
    print("%s 生产了 %s" % (name, res))
    # 把生产的vegetable放入到队列中
    q.put(res)
 
if __name__ == "__main__":
  #创建队列
  q = Queue()
  # 创建生产者
  p1 = Process(target=producer, args=(q, "kelly", "西瓜"))
  c1 = Process(target=consumer, args=(q, "peter",))
  p1.start()
  c1.start()
 
  # p1.join()
  # q.put(None)
  print("主进程")

2.2 执行结果

2.2.1 直接执行上面的代码的结果

直接执行会出现一个问题就是生产者生产完了,没有向消费者发送一个停止的信号,所以消费者一直会一直阻塞在q.get(),导致程序无法退出。

python多进程下的生产者和消费者模型

为了解决上面的问题,让消费者消费完了生产者的数据之后自动退出,就需要在生产者进程介绍的时候往队列里面put一个结束信号,消费者拿到这个信号,就退出消费进程。

主要是两个地方修改 ,把下方代码的注释打开就可以实现消费者消费完接收到生产者的结束信号就退出消费者进程了。

def consumer():
  if res is None: break
 
if __name__ == "__main__":
p1.join() 
q.put(None)

2.2.2 把注释打开后的运行结果

把注释打开后,消费者拿到了生产者发送的结束信号,可以正常退出程序了。

python多进程下的生产者和消费者模型

但如果有n个消费者,就需要发送n个结束信号,这种方式就不是那么简洁,像下面的代码这样:

from multiprocessing import Process, Queue
import time
 
 
# 消费者方法
def consumer(q, name):
  while True:
    res = q.get()
    if res is None: break
    print("%s 吃了 %s" % (name, res))
 
 
# 生产者方法
def producer(q, name, food):
  for i in range(3):
    time.sleep(1) # 模拟生产西瓜的时间延迟
    res = "%s %s" % (food, i)
    print("%s 生产了 %s" % (name, res))
    # 把生产的vegetable放入到队列中
    q.put(res)
 
 
if __name__ == "__main__":
  # 创建队列
  q = Queue()
  # 创建生产者
  p1 = Process(target=producer, args=(q, "kelly", "西瓜"))
  p2 = Process(target=producer, args=(q, "kelly2", "香蕉"))
  c1 = Process(target=consumer, args=(q, "peter",))
  c2 = Process(target=consumer, args=(q, "peter2",))
  c3 = Process(target=consumer, args=(q, "peter3",))
  p1.start()
  p2.start()
  c1.start()
  c2.start()
  c3.start()
 
  p1.join()
  p2.join()
  q.put(None)
  q.put(None)
  q.put(None)
  print("主进程")

其实我们现在就是生产者生产完数据之后想往队列里面发送一个结束信号,python语言提供了另外一种队列JoinableQueue([maxsize])来解决这种问题

三、JoinableQueue实现生产者消费者模型

3.1 JoinableQueue方法介绍

JoinableQueue([maxsize]) : A queue type which also supports join() and task_done() methods

q.task_done():消费者使用此方法发出信号,表示q.get()的返回项目已经被处理。

q.join():生产者调用此方法进行阻塞,直到队列中所有的项目均被处理;阻塞将持续到队列中的每个项目均调用q.task_done()方法为止。

3.2 JoinableQueue实现生产者消费者模型源码

from multiprocessing import Process,JoinableQueue
import time
 
 
# 消费者方法
def consumer(q, name):
  while True:
    res = q.get()
    if res is None: break
    print("%s 吃了 %s" % (name, res))
    q.task_done() # 发送信号给q.join(),表示已经从队列中取走一个值并处理完毕了
 
 
# 生产者方法
def producer(q, name, food):
  for i in range(3):
    time.sleep(1) # 模拟生产西瓜的时间延迟
    res = "%s %s" % (food, i)
    print("%s 生产了 %s" % (name, res))
    # 把生产的vegetable放入到队列中
    q.put(res)
  q.join() # 等消费者把自己放入队列的所有元素取完之后才结束
 
 
if __name__ == "__main__":
  # q = Queue()
  q = JoinableQueue()
  # 创建生产者
  p1 = Process(target=producer, args=(q, "kelly", "西瓜"))
  p2 = Process(target=producer, args=(q, "kelly2", "蓝莓"))
  # 创建消费者
  c1 = Process(target=consumer, args=(q, "peter",))
  c2 = Process(target=consumer, args=(q, "peter2",))
  c3 = Process(target=consumer, args=(q, "peter3",))
 
  c1.daemon = True
  c2.daemon = True
  c3.daemon = True
 
  p_l = [p1, p2, c1, c2, c3]
  for p in p_l:
    p.start()
  
  p1.join()
  p2.join()
  # 1.主进程等待p1,p2进程结束才继续执行
  # 2.由于q.join()的存在,生产者只有等队列中的元素被消费完才会结束
  # 3.生产者结束了,就代表消费者已经消费完了,也可以结束了,所以可以把消费者设置为守护进程(随着主进程的退出而退出)
 
  print("主进程")

3.3 运行结果

通过运行结果可以看出,生产者没有手动发送结束信号给消费者,而是通过JoinableQueue队列的方式也实现了生产者消费者模型。

python多进程下的生产者和消费者模型

到此这篇关于python多进程下的生产者和消费者模型的文章就介绍到这了,更多相关python多进程下的生产者和消费者内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python实现二叉搜索树
Feb 03 Python
利用Python破解验证码实例详解
Dec 08 Python
教大家玩转Python字符串处理的七种技巧
Mar 31 Python
Python实现单词翻译功能
Jun 06 Python
Python正则表达式常用函数总结
Jun 24 Python
解决python写入mysql中datetime类型遇到的问题
Jun 21 Python
使用python 写一个静态服务(实战)
Jun 28 Python
详解基于python-django框架的支付宝支付案例
Sep 23 Python
Keras在训练期间可视化训练误差和测试误差实例
Jun 16 Python
python使用隐式循环快速求和的实现示例
Sep 11 Python
scrapy中如何设置应用cookies的方法(3种)
Sep 22 Python
python神经网络 tf.name_scope 和 tf.variable_scope 的区别
May 04 Python
基于python实现检索标记敏感词并输出
May 07 #Python
Python3自动生成MySQL数据字典的markdown文本的实现
May 07 #Python
如何搭建pytorch环境的方法步骤
May 06 #Python
Python基于Tkinter编写crc校验工具
May 06 #Python
使用Python实现批量ping操作方法
May 06 #Python
Python super()函数使用及多重继承
May 06 #Python
python中shell执行知识点
May 06 #Python
You might like
PHP结合JQueryJcrop实现图片裁切实例详解
2014/07/24 PHP
网站防止被刷票的一些思路与方法
2015/01/08 PHP
PHP中array_keys和array_unique函数源码的分析
2016/02/26 PHP
Thinkphp5+uploadify实现的文件上传功能示例
2018/05/26 PHP
jQuery代码优化 选择符篇
2011/11/01 Javascript
解决3.01版的jquery.form.js中文乱码问题的解决方法
2012/03/08 Javascript
JS 修改URL参数(实现代码)
2013/07/08 Javascript
fixedBox固定div漂浮代码支持ie6以上大部分主流浏览器
2014/06/26 Javascript
JavaScript中Date对象的常用方法示例
2015/10/24 Javascript
jQuery  ready方法实现原理详解
2016/10/19 Javascript
JavaScript实现简易的天数计算器实例【附demo源码下载】
2017/01/18 Javascript
JS简单生成随机数(随机密码)的方法
2017/05/11 Javascript
Angular 2父子组件数据传递之@Input和@Output详解(下)
2017/07/05 Javascript
vue组件编写之todolist组件实例详解
2018/01/22 Javascript
Vue.js数字输入框组件使用方法详解
2019/10/19 Javascript
python获取外网IP并发邮件的实现方法
2017/10/01 Python
Python读取word文本操作详解
2018/01/22 Python
根据DataFrame某一列的值来选择具体的某一行方法
2018/07/03 Python
利用pyuic5将ui文件转换为py文件的方法
2019/06/19 Python
Django对models里的objects的使用详解
2019/08/17 Python
Python Numpy 控制台完全输出ndarray的实现
2020/02/19 Python
解决Python 异常TypeError: cannot concatenate 'str' and 'int' objects
2020/04/08 Python
opencv+python实现鼠标点击图像,输出该点的RGB和HSV值
2020/06/02 Python
Keras中的两种模型:Sequential和Model用法
2020/06/27 Python
Python+Opencv身份证号码区域提取及识别实现
2020/08/25 Python
Old Navy加拿大官网:美式休闲服饰品牌
2017/09/26 全球购物
领先的英国注册在线药房 :Simply Meds Online
2019/03/28 全球购物
澳大利亚网上买书:Angus & Robertson
2019/07/21 全球购物
会计专业自我鉴定范文
2013/10/06 职场文书
电子银行营销方案
2014/02/22 职场文书
最美孝心少年事迹材料
2014/08/15 职场文书
党的群众路线教育实践活动方案
2014/10/31 职场文书
中学生检讨书范文
2014/11/03 职场文书
《角的初步认识》教学反思
2016/02/17 职场文书
在Spring-Boot中如何使用@Value注解注入集合类
2021/08/02 Java/Android
Redis高并发缓存架构性能优化
2022/05/15 Redis