python 并发编程 多进程 生产者消费者模型介绍
一 生产者消费者模型介绍
为什么要使用生产者消费者模型
生产者指的是生产数据的任务,消费者指的是处理数据的任务,
生产数据目的,是为了给消费者处理。
在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
import time def producer():
'''生产者是厨师''' for i in range(1,4): # 模拟生产三个数据
res = "包子%s" % i
time.sleep(2)
print("生产者生产%s" % res) consumer(res) def consumer(res):
'''消费者吃包子''' time.sleep(1)
print("消费者消费%s" % res) if __name__ == "__main__":
producer() '''
生产者生产包子1
消费者消费包子1
生产者生产包子2
消费者消费包子2
生产者生产包子3
消费者消费包子3
'''
生产者必须等消费者,消费者也必须等生产者!
什么是生产者和消费者模型
生产者消费者模型是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

这个阻塞队列就是用来给生产者和消费者解耦的
二 生产者消费者模型实现
通过队列
from multiprocessing import Process
from multiprocessing import Queue
import time def producer(q): for i in range(1,6):
res = "包子%s" %i
time.sleep(0.5)
print("生产者生产%s" % res) # 现在不是给消费者了 放入数据 res 把包子放到队列
q.put(res) def consumer(q):
while True:
# 一直接取数据
res = q.get()
time.sleep(1)
print("消费者消费%s" % res) if __name__ == "__main__": # 容器
q = Queue() # 生产者们
# 需要传参数 把生产后数据的往队列里丢
p = Process(target=producer, args=(q,)) # 消费者们
c = Process(target=consumer, args=(q,)) p.start()
c.start()
print("主")
执行结果,不是生产一个消费一个,生成者与消费者互相不影响
主
生产者生产包子1
生产者生产包子2
生产者生产包子3
消费者消费包子1
生产者生产包子4
生产者生产包子5
消费者消费包子2
消费者消费包子3
消费者消费包子4
消费者消费包子5
此时的问题是主进程永远不会结束
原因是:生产者p在生产完后就结束了,但是消费者c在取空了队列之后,则一直处于死循环中且卡在q.get()这一步。(生产者从队列取不到数据就卡住)
一旦队列取空了 会被锁住 就卡住了,程序卡在消费者
解决:
解决方式无非是让生产者在生产完毕后,往队列中再发一个结束信号,这样消费者在接收到结束信号后就可以break出死循环
from multiprocessing import Process
from multiprocessing import Queue
import time def producer(q): for i in range(1,6):
res = "包子%s" %i
time.sleep(0.5)
print("生产者生产%s" % res) # 现在不是给消费者了 放入数据 res 把包子放到队列
q.put(res) def consumer(q):
while True:
# 接取数据
res = q.get()
# 消费者在最后一次收到None后退出
if res is None:break
time.sleep(1)
print("消费者消费%s" % res) if __name__ == "__main__": # 容器
q = Queue() # 生产者们
# 需要传参数 把生产后数据的往队列里丢
p = Process(target=producer, args=(q,)) # 消费者们
c = Process(target=consumer, args=(q,)) p.start()
c.start() # 保证所有子进程执行完 主进程才能工作,不然一直阻塞
p.join()
# 保证生产者把所有数据扔到队列后 然后发送结束信号
q.put(None)
print("主") '''
生产者生产包子1
生产者生产包子2
生产者生产包子3
消费者消费包子1
生产者生产包子4
生产者生产包子5
消费者消费包子2
主
消费者消费包子3
消费者消费包子4
消费者消费包子5
'''
如果有多个消费者 生产者时候
有几个消费者就需要发送几次结束信号
from multiprocessing import Process, Queue
import time def producer(q): for i in range(5):
res = "包子%s" %i
time.sleep(0.5)
print("生产者生产%s" % res) # 现在不是给消费者了 放入数据 res 把包子放到队列
q.put(res) def consumer(q):
while True:
# 接取数据
res = q.get()
if res is None:break
time.sleep(1)
print("消费者消费%s" % res) if __name__ == "__main__": # 容器
q = Queue() # 生产者们
# 需要传参数 把生产后数据的往队列里丢
p1 = Process(target=producer, args=(q,))
p2 = Process(target=producer, args=(q,))
p3= Process(target=producer, args=(q,)) # 消费者们
c1 = Process(target=consumer, args=(q,))
c2 = Process(target=consumer, args=(q,)) p1.start()
p2.start()
p3.start() c1.start()
c2.start() # 保证所有子进程执行完 主进程才能工作,不然一直阻塞
p1.join()
p2.join()
p3.join() # 发完数据后 发送结束信号 有几个消费者就应该来几个信号 q.put(None)
q.put(None)
print("主")
结束信号一定是跟在正常数据后面,保证所有消费者把正常数据取走以后,接下来取的是结束信号
结束信号应该在主进程里面确保所有的生产者,都生产完毕以后,才发送结束信号
其实我们的思路无非是发送结束信号而已,有另外一种队列提供了这种机制 可以点击这个文章
python 并发编程 多进程 生产者消费者模型介绍的更多相关文章
- python 并发编程 多进程 生产者消费者模型总结
生产者消费者模型总结 生产者消费者模型什么时候用? 1.程序中有两类角色 一类负责生产数据(生产者) 一类负责处理数据(消费者) 2.引入生产者消费者模型为了解决的问题是 平衡生产者与消费者之间的速度 ...
- python 之 并发编程(生产者消费者模型、守护进程的应用)
9.8 生产者消费者模型 该模型中包含两类重要的角色: 1.生产者:将负责造数据的任务比喻为生产者 2.消费者:接收生产者造出的数据来做进一步的处理的被比喻成消费者 实现生产者消费者模型三要素:1.生 ...
- day34 并发编程之生产者消费者模型 队列
1.守护进程(了解) """ 守护进程 表示 一个进程b 守护另一个进程a 当被守护的进程a结束后 那么b也跟着结束了 就像 皇帝驾崩 妃子殉葬 应用场景 之所以开启子进 ...
- python 并发编程 多进程 队列目录
python 并发编程 多进程 队列 python 并发编程 多进程 生产者消费者模型介绍 python 并发编程 多进程 生产者消费者模型总结 python 并发编程 多进程 JoinableQue ...
- python并发编程&多进程(二)
前导理论知识见:python并发编程&多进程(一) 一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_cou ...
- Python并发编程-多进程
Python并发编程-多进程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.多进程相关概念 由于Python的GIL全局解释器锁存在,多线程未必是CPU密集型程序的好的选择. ...
- python 并发编程 多进程 目录
python multiprocessing模块 介绍 python 开启进程两种方法 python 并发编程 查看进程的id pid与父进程id ppid python 并发编程 多进程 Proce ...
- python并发编程&多进程(一)
本篇理论居多,实际操作见: python并发编程&多进程(二) 一 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行) ...
- python 并发编程 多进程 互斥锁 目录
python 并发编程 多进程 互斥锁 模拟抢票 互斥锁与join区别
随机推荐
- Python 3标准库 第五章 数学运算
第五章数学运算-----------------------上下文解释:编程时,我们一般也是先给程序定义一些前提(环境变量.描述环境变化的全局变量等),这些“前提”就是上文,然后再编写各功能模块的代码 ...
- es6的Map结构
es6的Map结构主要解决Object的键名只能是单一属性的问题.它可以是字符串,对象,数组,等等 其中有个问题要注意一下,就是 var map = new Map(); map.set(['a'], ...
- C# 之抽象类
抽象类 抽象类中 .只包含抽象方法, .包含非抽象方法和抽象方法 .可使用get和set访问器 Example : public abstract class GeeksForGeeks { publ ...
- yiele函数
1.概念: 当调用Thread.yield()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽略这个暗示. 2.实战. 看下面例子 public class yiel ...
- react 的className动态修改
https://blog.csdn.net/suwyer/article/details/81481507(copy) <div style={{display: (index===this.s ...
- codefroces Round #201.B--Fixed Points
B. Fixed Points time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- phpexcel 导出数字类型字段导出错误或者为空解决办法 (原)
跟我们写excel时候一样,手机号或者较长的数字类型,或被科学计数法和谐,但是如果类型是字符串,长一些的数字就不受影响了. 解决导出被和谐的最简单易懂的,就是最前面拼接‘ ’ 空格,或者字母符号之类, ...
- Android_(菜单)选项菜单
Android系统中菜单分为Options Menu.Context Menu.Sub Men三种 Options Menu和Context Menu属于一级菜单 Sub Menu属于Options ...
- BOM—Browser Object Model and DOM—Document Object Model
浏览器对象模型的内涵是每个页面都是一个window对象,而dom是document为基准的模型,而document与wimdow.document指向相同,所以可以这么理解,bom模型的定义是包括do ...
- supsplk 服务器被植入木马 挖矿 cpu使用 700%
最近emr集群跑任务的时候总出现 task failed ,优化sql,调提交任务参数都没解决,最后再我排查时候,发现一个从节点的cpu使用800% 经过一些列排查,发现是被注入木马了, #被人种下的 ...