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实现简单的socket server实例
Apr 29 Python
Python通过RabbitMQ服务器实现交换机功能的实例教程
Jun 29 Python
Python操作mysql数据库实现增删查改功能的方法
Jan 15 Python
Python实现获取nginx服务器ip及流量统计信息功能示例
May 18 Python
Python3爬虫爬取百姓网列表并保存为json功能示例【基于request、lxml和json模块】
Dec 05 Python
python装饰器简介---这一篇也许就够了(推荐)
Apr 01 Python
用Python+OpenCV对比图像质量的几种方法
Jul 15 Python
Python PIL图片添加字体的例子
Aug 22 Python
python英语单词测试小程序代码实例
Sep 09 Python
深入浅析python 中的self和cls的区别
Jun 20 Python
python中 _、__、__xx__()区别及使用场景
Jun 30 Python
python+requests实现接口测试的完整步骤
Oct 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下对字符串的递增运算代码
2010/08/21 PHP
easyui的tabs update正确用法分享
2014/03/21 PHP
PH P5.2至5.5、5.6的新增功能详解
2014/07/14 PHP
php微信开发之带参数二维码的使用
2016/08/03 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
2017/11/14 PHP
Nginx+php配置文件及原理解析
2020/12/09 PHP
Domino中运用jQuery读取视图内容的方法
2009/10/21 Javascript
用js实现层随着内容大小动态渐变改变 推荐
2009/12/19 Javascript
ajax 缓存 问题 requestheader
2010/08/01 Javascript
YUI Compressor压缩JavaScript原理及微优化
2013/01/07 Javascript
JS中表单的使用小结
2014/01/11 Javascript
基于javascript实现的购物商城商品倒计时实例
2016/12/11 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
详解基于angular-cli配置代理解决跨域请求问题
2017/07/05 Javascript
老生常谈Bootstrap媒体对象
2017/07/06 Javascript
Vue实现购物小球抛物线的方法实例
2020/11/22 Vue.js
python多线程操作实例
2014/11/21 Python
python执行子进程实现进程间通信的方法
2015/06/02 Python
python3 requests中使用ip代理池随机生成ip的实例
2018/05/07 Python
Python爬虫包BeautifulSoup简介与安装(一)
2018/06/17 Python
基于树莓派的语音对话机器人
2019/06/17 Python
OpenCV 轮廓检测的实现方法
2019/07/03 Python
Python使用selenium + headless chrome获取网页内容的方法示例
2019/10/16 Python
python psutil监控进程实例
2019/12/17 Python
Python语法之精妙的十个知识点(装B语法)
2020/01/18 Python
Pandas读取csv时如何设置列名
2020/06/02 Python
解决Keras 中加入lambda层无法正常载入模型问题
2020/06/16 Python
keras 多任务多loss实例
2020/06/22 Python
Python自省及反射原理实例详解
2020/07/06 Python
美国孕妇装品牌:Destination Maternity
2018/02/04 全球购物
美国在线轮胎零售商:SimpleTire
2019/04/08 全球购物
青年创业培训欢迎词
2014/01/10 职场文书
机关党建工作汇报材料
2014/08/20 职场文书
学校运动会报道稿
2014/09/23 职场文书
机关作风建设心得体会
2014/10/22 职场文书
病危通知单
2015/04/17 职场文书