Fork me on GitHub

生产者消费者模型

一、什么是生产者消费者模型

  生产者消费者模型就是通过一个容器解决它们之间的强耦合问题,生产者与消费者之间依靠阻塞队列进行通讯,生产者与消费者之间不直接通讯,这样平衡了二者之间的处理能力,这里使用了进程、线程以及生成器实现了生产者消费者模型。

  在进程中分别开启了生产者和消费者的进程,它们之间的通讯依赖进程中的队列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()

 

posted @ 2019-10-16 21:05  iveBoy  阅读(866)  评论(0编辑  收藏  举报
TOP