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 匹配任意字符(包括换行符)的正则表达式写法
Oct 29 Python
python多进程操作实例
Nov 21 Python
Python编写百度贴吧的简单爬虫
Apr 02 Python
Python父目录、子目录的相互调用方法
Feb 16 Python
python处理自动化任务之同时批量修改word里面的内容的方法
Aug 23 Python
Python 3.6 中使用pdfminer解析pdf文件的实现
Sep 25 Python
利用Python产生加密表和解密表的实现方法
Oct 15 Python
python脚本后台执行方式
Dec 21 Python
Python3.6 中的pyinstaller安装和使用教程
Mar 16 Python
详解python中GPU版本的opencv常用方法介绍
Jul 24 Python
Pygame框架实现飞机大战
Aug 07 Python
Python机器学习实战之k-近邻算法的实现
Nov 27 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之require/include顺序 推荐
2011/01/02 PHP
php设计模式 Composite (组合模式)
2011/06/26 PHP
php简单获取文件扩展名的方法
2015/03/24 PHP
php通过exif_read_data函数获取图片的exif信息
2015/05/21 PHP
php ucwords() 函数将字符串中每个单词的首字符转换为大写(实现代码)
2016/05/12 PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
2019/09/30 PHP
laravel 实现用户登录注销并限制功能
2019/10/24 PHP
jquery 插件之仿“卓越亚马逊”首页弹出菜单效果
2008/12/25 Javascript
JSQL SQLProxy 的 php 版本代码
2010/05/05 Javascript
JavaScript中的16进制字符(改进)
2011/11/21 Javascript
JS返回上一页实例代码通过图片和按钮分别实现
2013/08/16 Javascript
javascript实现html页面之间参数传递的四种方法实例分析
2015/12/15 Javascript
AngularJS基础 ng-include 指令简单示例
2016/08/01 Javascript
原生js获取元素样式的简单方法
2016/08/06 Javascript
Vue.js绑定HTML class数组语法错误的原因分析
2016/10/19 Javascript
原生JS轮播图插件
2017/02/09 Javascript
JS按条件 serialize() 对应标签的使用方法
2017/07/24 Javascript
Electron + vue 打包桌面操作流程详解
2019/06/24 Javascript
新手快速入门JavaScript装饰者模式与AOP
2019/06/24 Javascript
Vue.js路由实现选项卡简单实例
2019/07/24 Javascript
vuex的数据渲染与修改浅析
2020/11/26 Vue.js
举例讲解Python设计模式编程的代理模式与抽象工厂模式
2016/01/16 Python
用不到50行的Python代码构建最小的区块链
2017/11/16 Python
对python读取zip压缩文件里面的csv数据实例详解
2019/02/08 Python
用Python在Excel里画出蒙娜丽莎的方法示例
2020/04/28 Python
Python+OpenCV图像处理——实现直线检测
2020/10/23 Python
解决pycharm 格式报错tabs和space不一致问题
2021/02/26 Python
美国知名生活购物网站:Goop
2017/11/03 全球购物
澳大利亚领先的美容护肤品零售商之一:SkincareStore
2018/01/22 全球购物
初中三好学生事迹材料
2014/01/13 职场文书
主办会计岗位职责
2014/03/13 职场文书
医院护士党的群众路线教育实践活动对照检查材料思想汇报
2014/10/04 职场文书
2015年世界无烟日活动总结
2015/02/10 职场文书
员工年度工作总结2015
2015/05/18 职场文书
党员证明模板
2015/06/19 职场文书
体育教师研修感悟
2015/11/18 职场文书