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使用rsa加密算法模块模拟新浪微博登录
Jan 22 Python
python基于右递归解决八皇后问题的方法
May 25 Python
Python中装饰器兼容加括号和不加括号的写法详解
Jul 05 Python
Python探索之Metaclass初步了解
Oct 28 Python
python实现list由于numpy array的转换
Apr 04 Python
浅谈python 读excel数值为浮点型的问题
Dec 25 Python
pyqt5实现登录界面的模板
May 30 Python
Python中变量的输入输出实例代码详解
Jul 28 Python
python实点云分割k-means(sklearn)详解
May 28 Python
python中pop()函数的语法与实例
Dec 01 Python
python 读取yaml文件的两种方法(在unittest中使用)
Dec 01 Python
教你怎么用Python监控愉客行车程
Apr 29 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程序员应具有的7种能力小结
2014/11/27 PHP
php绘制一个扇形的方法
2015/01/24 PHP
jquery validate poshytip 自定义样式
2012/11/26 Javascript
你必须知道的Javascript知识点之&quot;深入理解作用域链&quot;的介绍
2013/04/23 Javascript
js函数内变量的作用域分析
2015/01/12 Javascript
JS表的模拟方法
2015/02/05 Javascript
jQuery实现指定内容滚动同时左侧或其它地方不滚动的方法
2015/08/08 Javascript
JavaScript兼容性总结之获取非行间样式案例
2016/08/07 Javascript
jQuery的extend方法【三种】
2016/12/14 Javascript
JS利用正则表达式实现简单的密码强弱判断实例
2017/06/16 Javascript
深入理解Webpack 中路径的配置
2017/06/17 Javascript
在vue中获取dom元素内容的方法
2017/07/10 Javascript
webpack实现一个行内样式px转vw的loader示例
2018/09/13 Javascript
vue-cli3 从搭建到优化的详细步骤
2019/01/20 Javascript
JS实现数组深拷贝的方法分析
2019/03/06 Javascript
vue的滚动条插件实现代码
2019/09/07 Javascript
layui对工具条进行选择性的显示方法
2019/09/19 Javascript
Vue实现导航栏的显示开关控制
2019/11/01 Javascript
javascript中contains是否包含功能实现代码(扩展字符、数组、dom)
2020/04/07 Javascript
python网络编程调用recv函数完整接收数据的三种方法
2017/03/31 Python
django自带的server 让外网主机访问方法
2018/05/14 Python
运用Python的webbrowser实现定时打开特定网页
2019/02/21 Python
python读csv文件时指定行为表头或无表头的方法
2019/06/26 Python
python中将两组数据放在一起按照某一固定顺序shuffle的实例
2019/07/15 Python
python多线程扫描端口(线程池)
2019/09/04 Python
python 实现字符串下标的输出功能
2020/02/13 Python
使用pygame编写Flappy bird小游戏
2020/03/14 Python
python异步Web框架sanic的实现
2020/04/27 Python
如何用python 操作zookeeper
2020/12/28 Python
Hawes & Curtis澳大利亚官网:英国经典服饰品牌
2018/10/29 全球购物
机电专业大学生职业规划书范文
2014/02/25 职场文书
办公设备采购方案
2014/03/16 职场文书
小学生学雷锋演讲稿
2014/04/25 职场文书
公司总经理助理岗位职责
2014/07/09 职场文书
2015年乡镇妇联工作总结
2015/05/19 职场文书
Mysql 性能监控及调优
2021/04/06 MySQL