多进程、多线程、生成器实现生产者消费者模型

多线程实现

多线程实现生产者消费者模型的逻辑十分简单,生产者与消费者之间通过队列来进行通讯,所以生产者不用等待消费者消费,直接丢给队列,同理,消费者也是一样,不用通过生产者取得数据,而是从队列里面拿取数据。这样,队列就相当于一个缓冲区,一个容器,平衡生产者与消费者的处理能力:

import random
from threading import Thread
from queue import Queue


class Producer(Thread):
    def __init__(self, name, q):
        super().__init__()
        self.name = name
        self.q = q

    def run(self):
        while True:
            item = random.randint(1, 99)
            self.q.put(item)
            print('product: {}'.format(item))


class Consumer(Thread):
    def __init__(self, name, q):
        super().__init__()
        self.name = name
        self.q = q
        
    def run(self):
        while True:
            item = self.q.get()
            print('consum: {}'.format(item))
            self.q.task_done()

if __name__ == '__main__':
    q = Queue(10)
    q.join()
    p = Producer('p1', q)
    c = Consumer('c1', q)
    p.start()
    c.start()

输出:

product: 14
product: 58
product: 8
product: 96
consum: 14
product: 93
product: 87
product: 88
product: 38
consum: 58
consum: 8
consum: 96
consum: 93
consum: 87
consum: 88
consum: 38
product: 21
consum: 21
...

多进程实现

多进程实现生产者消费者模型的代码与多线程版本类似:

import random
from multiprocessing import Process, Queue


class Producer(Process):
    def __init__(self, name, q):
        super().__init__()
        self.name = name
        self.q = q

    def run(self):
        while True:
            item = random.randint(0, 99)
            self.q.put(item)
            print('product: {}'.format(item))


class Consumer(Process):
    def __init__(self, name, q):
        super().__init__()
        self.name = name
        self.q = q

    def run(self):
        while True:
            item = self.q.get()
            print('consum: {}'.format(item))


if __name__ == '__main__':
    q = Queue(10)
    p = Producer('p1', q)
    c = Consumer('c1', q)
    p.start()
    c.start()

输出:

product: 47
product: 98
product: 43
product: 91
product: 70
product: 78
product: 14
product: 7
product: 72
product: 86
consum: 47
product: 89
consum: 98
consum: 43
...

生成器实现

def consumer():
    while True:
        item = yield
        print('consume {}'.format(item))

        
def producer():
    c.send(None) # 激活消费者生成器
    while True:
        item = random.randint(0, 99)
        print('product {}'.format(item))
        c.send(item) 


c = consumer()  # 消费者生成器
producer()      # 生产者函数

输出如下:

product 0
consume 0
product 91
consume 91
product 44
consume 44
product 68
consume 68
product 43
consume 43
....

我们也可以交换send和yield的位置,让消费者向生产者请求数据,代码如下:

def consumer():
    while True:
        item = p.send(None)
        if item is None:
            print('...')
        print('consume {}'.format(item))


def producer():
    while True:
        item = random.randint(0, 99)

        print('product {}'.format(item))
        yield item


p = producer()  # 生产者生成器
consumer()      # 消费者函数

也能够得到期望的输出:

product 34
consume 34
product 83
consume 83
product 40
consume 40
product 45
consume 45
...

通过生成器实现生产者消费者模型,CPU的有效利用率理论上能达到100%。若通过多线程来实现生产者消费者模型,queue会在full或empty时候阻塞;若通过多进程来实现生产者消费者模型,进程间的创建、切换、销毁要耗费大量CPU资源。

你可能感兴趣的:(多进程、多线程、生成器实现生产者消费者模型)