33. 生产者消费者模型
一、生产者消费者模型
假如有两个进程 A 和 B,它们共享一个 固定大小的缓冲区 ,A 进程产生数据放入缓冲区,B 进程从缓冲区中取出数据进行计算,那么这里其实就是一个生产者和消费者的模式,A 相当于生产者,B 相当于消费者。
在多线程开发中,如果生产者生产数据的速度很快,而消费者消费数据的速度很慢,那么生产者就必须等待消费者消费完了数据才能够继续生产数据,因为生产那么多也没有地方放;同理如果消费者的速度大于生产者那么消费者就会经常处理等待状态,所以为了达到生产者和消费者生产数据和消费数据之间的 平衡,那么就需要一个缓冲区用来存储生产者生产的数据,所以就引入了 生产者-消费者模式。
我们需要保证生产者不会在缓冲区满的时候继续向缓冲区放入数据,而消费者也不会在缓冲区空的时候,消耗数据。当缓冲区满的时候,生产者会进入休眠状态,当下次消费者开始消耗缓冲区的数据时,生产者才会被唤醒,开始往缓冲区中添加数据;当缓冲区空的时候,消费者也会进入休眠状态,直到生产者往缓冲区中添加数据时才会被唤醒。
import time
import random
from multiprocessing import Process,JoinableQueue
def productor(name,food,q):
for i in range(10):
# 模拟延迟
time.sleep(random.randint(1,3))
data = f"【{name}】生产了第 {i+1} 个【{food}】"
print(data)
# 将数据放入队列中
q.put(data)
def consumer(name,q):
while True:
time.sleep(random.randint(1,3))
food = q.get()
print(f"【{name}】吃了 {food}")
q.task_done() # 告诉队列你已经从里面去除了一个数据并且处理完了了
if __name__ == "__main__":
q = JoinableQueue(10)
p1 = Process(target=productor,args=("星光","包子",q))
p2 = Process(target=productor, args=("冰心", "寿司", q))
c1 = Process(target=consumer, args=("小樱", q))
c2 = Process(target=consumer, args=("小娜", q))
# 将消费者设置为守护进程
c1.daemon = True
c2.daemon = True
# 启动进程
p1.start()
p2.start()
c1.start()
c2.start()
p1.join()
p2.join()
"""
JoinableQueue 每当你往该队列中存入数据的时候,内部会有一个计数器+1
每当你调用task_done()的时候,计数器-1
q.join() 当计数器为0的时候,才往后运行
只要q.join()执行完毕,说明消费者处理完数据了
"""
q.join() # 等待队列中所有的数据被取完在执行下面的代码