• 生产者消费者模型


    万恶的win10,吃饭的时候自动更新把我写了一大半的博客搞没了,只能重写一遍了。。。

    1 什么是生产者消费者模型
    生产者:比喻的是程序中负责产生数据的任务
    消费者:比喻的是程序中负责处理数据的任务

    生产者->共享的介质(队列)<-消费者

    2 为何用
    实现了生产者与消费者的解耦和,生产者可以不停地生产,消费者也可以不停地消费
    从而平衡了生产者的生产能力与消费者消费能力,提升了程序整体运行的效率

    3.什么时候用?
    当我们的程序中存在明显的两类任务,一类负责产生数据,另外一类负责处理数据
    此时就应该考虑使用生产者消费者模型来提升程序的效率。


    生产消费者基本模型:一个生产者,一个消费者
    代码有注释
    from multiprocessing import Queue,Process
    import time
    import os
    import random
    # 两个子进程,一个生产一个消费,一个把生产的全放进队列里,最后添加个None。一个从创造好的队列取出数据,
    # 直到取出最后一个数据,循环结束。
    # 只有一个生产者和消费者,所以生产结束直接在最后加个None,消费者取到None代表队列空了
    def producer(q):
        for i in range(10):
            res='包子%s' %i
            time.sleep(random.randint(1,3))
            # 往队列里丢
            q.put(res)
            print('33[42m%s 生产了 %s[0m33' %(os.getpid(),res))
        q.put(None)
    
    def consumer(q):
        while True:
            #从队列里取走
            res=q.get()
            if res is None:break
            time.sleep(random.randint(1,3))
            print('33[41m%s 吃了 %s[0m33' %(os.getpid(),res))
    
    if __name__ == '__main__':
        q=Queue()  # <multiprocessing.queues.Queue object at 0x0000020D141485C0>
        print(q)
        # 生产者们
        p1=Process(target=producer,args=(q,))
        # print(q)
        # 消费者们
        c1=Process(target=consumer,args=(q,))
        # print(q)
    
        p1.start()
        c1.start()
    
        print('')
    生产消费基本模型

    多个生产者和多个消费者

    代码有注释

    from multiprocessing import Queue,Process
    import time
    import os
    import random
    
    def producer(name,food,q):
        for i in range(3):
            res='%s%s' %(food,i)
            time.sleep(random.randint(1,3))
            # 往队列里丢
            q.put(res)
            print('33[45m%s 生产了 %s33[0m' %(name,res))
        # q.put(None)
    
    def consumer(name,q):
        while True:
            #从队列里取走
            res=q.get()
            if res is None:break
            time.sleep(random.randint(1,3))
            print('33[46m%s 吃了 %s33[0m' %(name,res))
    
    if __name__ == '__main__':
        q=Queue()
        # 生产者们
        p1=Process(target=producer,args=('egon','包子',q,))
        p2=Process(target=producer,args=('杨军','泔水',q,))
        p3=Process(target=producer,args=('猴老师','',q,))
        # 消费者们
        c1=Process(target=consumer,args=('Alex',q,))
        c2=Process(target=consumer,args=('wupeiqidsb',q,))
    
        p1.start()
        p2.start()
        p3.start()
        c1.start()
        c2.start()
    
        p1.join()
        p2.join()
        p3.join()
        # 在p1p2p3都结束后,才应该往队列里放结束信号,有几个消费者就应该放几个None
        q.put(None)
        q.put(None)
    
        print('')
    多个生产者和多个消费者

    消费者给生产者发信号

    简单说下流程:先从mulitprocessing模块导入JoinableQueue和Process类,再导入时间模块。定义一个生产者函数,一个消费者函数。

    在main下面通过JoinableQueue产生一个队列对象q,产生多个生产者和消费者进程,子进程向操作系统发起请求启动子进程。

    填充生产者函数,循环产生值,利用q.put(res)把产生的res放进队列中,模拟延迟,每次产生值后睡眠1s。消费者没有固定的循环条件,

    所以用while True,消费者从队列中取值q.get(),模拟网络延迟,取完值后睡眠1s,然后q.task_done()表示告诉队列已经有一个数据被取走了。

    在main下面,加上q.join()是为了等待队列被取干净。取干净之后进行下一段代码。

    # 消费者给生产者发信号
    from multiprocessing import JoinableQueue,Process  # 可以被join住的,等待队列结束,数据取干净了,队列就算结束了
    import time
    import os
    import random
    
    def producer(name,food,q):
        for i in range(3):
            res='%s%s' %(food,i)
            time.sleep(random.randint(1,3))
            # 往队列里丢
            q.put(res)
            print('33[45m%s 生产了 %s33[0m' %(name,res))
        # q.put(None)
    
    def consumer(name,q):
        while True:
            #从队列里取走
            res=q.get()
            if res is None:break
            time.sleep(random.randint(1,3))
            print('33[46m%s 吃了 %s33[0m' %(name,res))
            q.task_done()  # 一个任务结束  告诉队列已经有一个数据被取走了,执行完一次get应该来个q.task_done()
    
    if __name__ == '__main__':
        # 生产者们
        q=JoinableQueue()
        p1=Process(target=producer,args=('egon','包子',q,))
        p2=Process(target=producer,args=('杨军','泔水',q,))
        p3=Process(target=producer,args=('猴老师','',q,))
        # 消费者们
        c1=Process(target=consumer,args=('Alex',q,))
        c2=Process(target=consumer,args=('wupeiqidsb',q,))
        c1.daemon=True  # 两个消费者建立守护进程 因为
        c2.daemon=True
    
        p1.start()
        p2.start()
        p3.start()
        c1.start()
        c2.start()
    
        p1.join()
        p2.join()
        p3.join()
    
        q.join() # 等待队列被取干净 如果队列没被取干净,就一直停在这儿
        # 统计队列有多少个值,有个task_done 就减一,队列被取光了,就执行下一个代码
        # 如果直接放q.join()那么如果队列只有三个值,他也会执行结束。所以要在所有生产者生产完才q.join()
        # q.join()
        # 结束意味着主进程的代码运行完毕--->(生产者运行完毕)+队列中的数据也被取干净了->消费者没有存在的意义
    
        print('')
    JoinableQueue


  • 相关阅读:
    在ubuntu9中安装配置java postgresql pljava tsearch2
    Zend中配置Memcached
    PHP 截取字符串专题(转)
    网络执法官.P2P终结者等监控网络流量控制软件的原理和防范
    C++中的浮点数格式控制
    HTML教程
    网络执法官.P2P终结者等监控网络流量控制软件的原理和防范
    CodeGear RADstudio 2007+Sp3下载地址及破解
    HTML教程
    CodeGear RADstudio 2007+Sp3下载地址及破解
  • 原文地址:https://www.cnblogs.com/Roc-Atlantis/p/9301635.html
Copyright © 2020-2023  润新知