生产消费者模型是将消费者的充分处理完生产的数据,并将效率最大化。
生产者: 泛指产生数据的一方
消费者: 泛指处理数据的一方
一、具体的解决方法:
1、案例:
食堂饭店是生产者
我们吃饭的人就是消费者
2、案例分析
他们之间有什么问题
效率低 因为双方的处理速度不同 一个快一个慢 则双方需要相互等待
1.先将双方解开耦合,让不同的进程负责不同的任务
2.提供一个共享的容器 来平衡双方的能力,之所用进程队列是因为队列 可以在进程间共享
案例1:
from multiprocessing import Process,Queue
import requests
import re,os,time,random
# 生产者任务
def product(urls,q):
i = 0
for url in urls:
response = requests.get(url)
text = response.text
# 将生产完成的数据放入队列中
time.sleep(random.random())
q.put(text)
i += 1
print(os.getpid(),"生产了第%s个数据" % i)
def customer(q):
i = 0
while True:
text = q.get()
time.sleep(random.random())
res = re.findall('src=//(.*?) width', text)
i += 1
print(" 第%s个任务获取到%s个img" % (i,len(res)))
if __name__ == '__main__':
urls = [
"http://www.baidu.com",
"http://www.baidu.com",
"http://www.baidu.com",
"http://www.baidu.com",
]
# 创建一个双方能共享的容器
q = Queue()
# 生产者进程
p1 = Process(target=product,args=(urls,q))
p1.start()
# 消费者进程
c = Process(target=customer,args=(q,))
c.start()
问题: 消费不知道什么时候结束
案例进阶:
joinableQueue 继承自Queue 用法一致,
增加了join 和taskDone
join是个阻塞函数 会阻塞直到taskdone的调用次数等于 存入的元素个数 可以用于表示队列任务处理完成
案例:
from multiprocessing import Process,JoinableQueue
import requests
import re,os,time,random
"""
生产者 负责生产热狗
消费者 负责吃热狗
"""
# 生产者任务
def product(q,name):
for i in range(5):
dog = "%s的热狗%s" % (name,(i + 1))
time.sleep(random.random())
print("生产了",dog)
q.put(dog)
# 吃热狗
def customer(q):
while True:
dog = q.get()
time.sleep(random.random())
print("消费了%s" % dog)
q.task_done() # 标记这个任务处理完成
if __name__ == '__main__':
# 创建一个双方能共享的容器
q = JoinableQueue()
# 生产者进程
p1 = Process(target=product,args=(q,"上海分店"))
p2 = Process(target=product,args=(q,"北京分店"))
p1.start()
p2.start()
# 消费者进程
c = Process(target=customer,args=(q,))
# c.daemon = True # 可以将消费者设置为守护进程 当主进程确认 任务全部完成时 可以随着主进程一起结束
c.start()
p1.join()
p2.join() # 代码走到这里意味着生产方完成
q.join() # 意味着队列中的任务都处理完成了
# 结束所有任务
c.terminate() # 直接终止消费者进程
# 如何判定今天的热狗真的吃完了
# 1.确定生成者任务完成
# 2.确定生出来的数据已经全部处理完成
redis 消息队列
MQ 消息队列
常用来做流量削峰 保证服务不会因为高并发而崩溃