python学习笔记-生产者消费者模型及代码实现

本文为了说明例子,用中文作为变量写在了程序里面,一般编程最好不要那么写
生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。

这里实现如下情况的生产–消费模型:

生产者不断交替地生产两组数据“姓名–1 --> 内容–1”,“姓名–2--> 内容–2”,消费者不断交替地取得这两组数据,这里的“姓名–1”和“姓名–2”模拟为数据的名称,“内容–1 ”和“内容–2 ”模拟为数据的内容。

由于本程序中牵扯到线程运行的不确定性,因此可能会出现以下问题:

假设生产者线程刚向数据存储空间添加了数据的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程将把信息的名称和上一个信息的内容联系在一起;
生产者生产了若干次数据,消费者才开始取数据,或者是,消费者取完一次数据后,还没等生产者放入新的数据,又重复取出了已取过的数据。
问题 1 很明显要靠同步来解决,问题 2 则需要线程间通信,生产者线程放入数据后,通知消费者线程取出数据,消费者线程取出数据后,通知生产者线程生产数据,这里用 wait/notify 机制来实现。

from multiprocessing import Process, Queue, JoinableQueue
import time
import random


def 生产者(name,food,q):
    for i in range(5):
        data = '%s生产了%s%s'%(name,food,i)
        # 模拟延迟
        time.sleep(random.randint(1,3))
        print(data)
        # 将数据放入 队列中
        q.put(data)


def 消费者(name,q):
    
    while True:
        food = q.get()  # 没有数据就会卡住
        # 判断当前是否有结束的标识
        # if food is None:break
        time.sleep(random.randint(1,3))#每个人的手速不同
        print('%s吃了%s'%(name,food))
        A.task_done()  # 告诉队列你已经从里面取出了一个数据并且处理完毕了


if __name__ == '__main__':
    A = Queue()
    A = JoinableQueue()
    B1 = Process(target=生产者,args=('厨师A','包子',A))
    B2 = Process(target=生产者,args=('厨师B','油条',A))
    C1 = Process(target=消费者,args=('客人A',A))
    C2 = Process(target=消费者,args=('客人B',A))
    B1.start()
    B2.start()
    # 将消费者设置成守护进程
    C1.daemon = True
    C2.daemon = True
    C1.start()
    C2.start()
    B1.join()
    B2.join()
    # 等待生产者生产完毕之后 往队列中添加特定的结束符号
    A.put(None)  # 肯定在所有生产者生产的数据的末尾
    A.put(None)  # 肯定在所有生产者生产的数据的末尾
    A.join()  # 等待队列中所有的数据被取完再执行往下执行代码

    #JoinableQueue 每当你往该队列中存入数据的时候 内部会有一个计数器+1
    #没当你调用task_done的时候 计数器-1
    #A.join() 当计数器为0的时候 才往后运行

    # 只要A.join执行完毕 说明消费者已经处理完数据了  消费者就没有存在的必要了
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丰。。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值