多方式实现生产者与消费者

生产者(producer)与消费者(consumer)

1.通过Queue队列实现
from multiprocessing import Queue
import time
import random
from multiprocessing import Process, Queue


def producer(q: Queue, name: str, food: str):
    for i in range(1, 10 + 1):
        time.sleep(random.uniform(0.1, 0.8))
        print(f'{name}生产了{i}份{food}!')
        q.put((i, food))


def consumer(q: Queue, name: str):
    while True:
        res = q.get()
        if res is None:
            break
        time.sleep(random.uniform(0.1, 0.5))
        print(f'{name}吃了{res[0]}份{res[1]}!')


if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=producer, args=(q, '小日', '果冻'))
    p1.start()
    p2 = Process(target=producer, args=(q, '小月', '糖果'))
    p2.start()
    c = Process(target=consumer, args=(q, '小华'))
    c.start()
    p1.join()
    p2.join()
    q.put(None)
2.通过JoinableQueue实现
from multiprocessing import JoinableQueue
  • task_done()方法

    比原先队列多了一个方法task_done(),当队列中的数据处理完会反馈给队列!

  • join()方法:

    阻塞方法,当队列中的数据都task_done()完成后,join()就结束了,

    这样可以让生产者与消费者更完美的处理完数据!

import time
import random
from multiprocessing import Process, JoinableQueue


def producer(q, name: str, food: str):
    for i in range(1, 10 + 1):
        time.sleep(random.uniform(0.1, 0.8))
        print(f'{name}生产了{i}份{food}!')
        q.put((i, food))


def consumer(q, name: str):
    while True:
        res = q.get()
        time.sleep(random.uniform(0.1, 0.5))
        print(f'{name}吃了{res[0]}份{res[1]}!')
        q.task_done()


if __name__ == '__main__':
    q = JoinableQueue()
    p1 = Process(target=producer, args=(q, 'big', '果冻'))
    p1.start()
    p2 = Process(target=producer, args=(q, 'small', '棒冰'))
    p2.start()
    c = Process(target=consumer, args=(q, '小华'))
    c.daemon = True
    c.start()
    p1.join() # p1和p2的阻塞是为了让数据都生产结束,这样队列才能反馈处理结果
    p2.join()
    q.join()# 当队列数据反馈都数据结束后,阻塞才会结束
3.通过管道Pipe实现
from multiprocessing import Pipe

在管道中有2端,在例题中我们取left,right,管道在子进程中传递了进去后,不使用的端我们要关闭,比如left,而在主进程中我们不使用right端,所以在left端发送完信息后,也要关闭right端口。
当管道中就剩下一个端口的时候,如果数据取完在继续取数据,就会出现EOFError
我们通过对于异常的捕获,让消费者实现循环的关闭,从而实现管道之间的数据生产和消费。

注:管道是基于socket实现的所以收的时候会处于阻塞状态

from multiprocessing import Pipe, Process
import time
import random


def producer(left, right, name, food):
    right.close()
    for i in range(20):
        time.sleep(random.uniform(0.1, 0.5))
        print(f'{name}生产了{i}份{food}')
        left.send((i, food))
    left.close()


def consumer(left, right, name):
    left.close()
    while True:
        try:
            res = right.recv()
            time.sleep(random.uniform(0.1, 0.5))
            print(f'{name}吃了{res[0]}份{res[1]}')
        except EOFError:
            break


if __name__ == '__main__':
    left, right = Pipe()
    p1 = Process(target=producer, args=(left, right, 'Tom', '水果'))
    p1.start()
    c1 = Process(target=consumer, args=(left, right, '小明'))
    c1.start()
    p1.join()
    left.close()
    right.close()
    c1.join()
    print('主进程结束')
posted @ 2021-08-10 19:02  缘兮Fate  阅读(53)  评论(0)    收藏  举报