一、什么是生产者消费者模型
生产者消费者模型就是通过一个容器解决它们之间的强耦合问题,生产者与消费者之间依靠阻塞队列进行通讯,生产者与消费者之间不直接通讯,这样平衡了二者之间的处理能力,这里使用了进程、线程以及生成器实现了生产者消费者模型。
在进程中分别开启了生产者和消费者的进程,它们之间的通讯依赖进程中的队列Queue来实现的。在线程中分别开启了生产者和消费者线程,它们之间的通讯依赖queue中的Queue完成通讯。协程的使用生成器简单的实现。
使用进程的方式会耗费大量cpu的资源(包括进程的创建、切换、销毁);线程的方式相比进程来讲切换会较少损耗cpu的资源;协程的方式理论上来讲cpu的利用率达到100%,所以协程应该是较为理想的选择。
二、使用进程实现生产者消费者模型
from multiprocessing import Process
from multiprocessing import Queue
def producer(q, name):
# 生产者生产20个数据
for i in range(20):
q.put(str(i))
print("%s生产第%s个" % (name, i))
def consumer(q, name):
while True:
# 从队列中获取数据
data = q.get()
if data:
print("%s消费第%s个" % (name, data))
else:
break
if __name__ == '__main__':
q = Queue()
# 创建10个生产者
p_pro_list = []
for i in range(10):
p_pro = Process(target=producer, args=(q, "生产者%s" % i))
p_pro_list.append(p_pro)
p_pro.start()
# 等待所有的生产进程结束
for j in p_pro_list:
j.join()
# 然后再q中加入结束标示,用于消费者判断队列中是否还有数据,有多少个生产者加入多少个None
for k in p_pro_list:
q.put(None)
# 创建5个消费者
p_con_list = []
for i in range(5):
p_con = Process(target=consumer, args=(q, "消费者%s" % i))
p_con_list.append(p_con)
p_con.start()
for j in p_con_list:
j.join()
三、使用线程实现生产者消费者模型
import threading
from queue import Queue
def producer(q, name):
for item in range(20):
q.put(item)
print("%s-%s" % (name, item))
def consumer(q, name):
while True:
item = q.get()
if item is None:
break
print("%s-%s" % (name, item))
q.task_done() # 任务完成后向队列发送一个讯号通知一下
if __name__ == '__main__':
q = Queue()
# 等待消费者消费q中的产品,与task_done搭配使用
q.join()
# 生产者生产产品
t_pro = threading.Thread(target=producer, args=(q, '生产者生产'))
t_pro.start()
# 消费者消费产品
t_con = threading.Thread(target=consumer, args=(q, '消费者消费'))
t_con.start()
四、使用线程实现生产者消费者模型
协程的运行是由程序员控制而非操作系统,所以可以通过yield进行简单的实现。
import time
import random
def consumer():
while True:
item = yield
print("消费%s" % item)
def producer():
# 第一次调用生成器时,使用next()语句或是send(None),不能使用send发送一个非None的值,否则会出错的。
c.send(None) # 相当于c.next()激活生成器
while True:
time.sleep(1)
item = random.randint(1, 50)
print("生产%s" % item)
# 进入生成器函数,此时将item赋值给yield并且传回。相当于把item赋值给consumer中的item。
c.send(item)
if __name__ == '__main__':
# 消费者生成器
c = consumer()
producer()