• python_ joinablequeue详解


    2019-5-20未命名文件

    欢迎使用 小书匠(xiaoshujiang)编辑器,您可以通过 小书匠主按钮>模板 里的模板管理来改变新建文章的内容。

    joinablequeue实现生产者消费者模型

    1、使用Queue实现的代码

    import time
    import random
    from multiprocessing import Process,Queue
    
    def producer(q,name,food):
        for i in range(2):
            time.sleep(random.random())
            fd = '%s%s'%(food,i)
            q.put(fd)
            print('%s生产了一个%s'%(name,food))
    
    def consumer(q,name):
        while True:
            food = q.get()
            if not food:break
            time.sleep(random.randint(1,3))
            print('%s吃了%s'%(name,food))
    
    
    def cp(c_count,p_count):
        q = Queue(10)
        for i in range(c_count):
            Process(target=consumer, args=(q, '灰太狼')).start()
        p_l = []
        for i in range(p_count):
            p1 = Process(target=producer, args=(q, '喜洋洋', '包子'))
            p1.start()
            p_l.append(p1)
        for p in p_l:p.join()
        for i in range(c_count):
            q.put(None)
    if __name__ == '__main__':
        cp(2,3)
    ----------------结果:
    喜洋洋生产了一个包子
    喜洋洋生产了一个包子
    喜洋洋生产了一个包子
    喜洋洋生产了一个包子
    喜洋洋生产了一个包子
    喜洋洋生产了一个包子
    灰太狼吃了包子1
    灰太狼吃了包子0
    灰太狼吃了包子0
    灰太狼吃了包子0
    灰太狼吃了包子1
    灰太狼吃了包子1

    2、使用joinablequeue实现队列
    (1)消费者不需要判断从队列里拿到None再退出执行消费者函数了
    (2)消费者每次从队列里面q.get()一个数据,处理过后就使用队列.task_done()
    (3)生产者for循环生产完所有产品,需要q.join()阻塞一下,对这个队列进行阻塞。
    (4)启动一个生产者,启动一个消费者,并且这个消费者做成守护进程,然后生产者需要p.join()阻塞一下。
    (5)我启动了生产者之后,生产者函数一直在生成数据,直到生产完所有数据将队列q.join()一下,意思是当我生产的数据都被消费者消费完之后 队列的阻塞才结束。
    (6)结束过程:消费者这边是每消费完一个数据给队列返回一个q.task_done(),直到所有的数据都被消费完之后,生产者函数这边的队列.阻塞结束了,队列阻塞结束了生产者函数执行结束了。生产者函数结束了,那么p.join()生产者进程对象就结束了。生产者进程对象结束了整个主进程的代码就执行结束了。主进程代码结束了守护进程及消费者进程也结束了

    import time
    import random
    from  multiprocessing import JoinableQueue,Process
    def producer(q,name,food):
        for i in range(5):
            time.sleep(random.random())
            fd = '%s%s'%(food,i+1)
            q.put(fd)
            print('%s生产了一个%s'%(name,food))
        q.join()#(3)生产者for循环生产完所有产品,需要q.join()阻塞一下,对这个队列进行阻塞。
    #(5)我启动了生产者之后,生产者函数一直在生成数据,直到生产完所有数据将队列q.join()一下,意思是当我生产的数据都被消费者消费完之后 队列的阻塞才结束。
    def consumer(q,name): #(1)消费者不需要像Queue那样判断从队列里拿到None再退出执行消费者函数了
        while True:
            food = q.get()
            time.sleep(random.random())
            print('%s吃了%s'%(name,food))
            q.task_done() #(2)消费者每次从队列里面q.get()一个数据,处理过后就使用队列.task_done()
    if __name__ == '__main__':
        jq = JoinableQueue()
        p =Process(target=producer,args=(jq,'喜洋洋','包子')) #
        p.start() #(4)启动一个生产者,启动一个消费者,并且这个消费者做成守护进程,然后生产者需要p.join()阻塞一下。
        c = Process(target=consumer,args=(jq,'灰太狼'))
        c.daemon = True #
        c.start()
        p.join() 
    #(6)结束过程:消费者这边是每消费完一个数据给队列返回一个q.task_done(),直到所有的数据都被消费完之后,生产者函数这边的队列.阻塞结束了,队列阻塞结束了生产者函数执行结束了。生产者函数结束了,那么p.join()生产者进程对象就结束了。生产者进程对象结束了整个主进程的代码就执行结束了。主进程代码结束了守护进程即消费者进程也结束了
    ---------------结果:
    喜洋洋生产了一个包子
    灰太狼吃了包子1
    喜洋洋生产了一个包子
    喜洋洋生产了一个包子
    喜洋洋生产了一个包子
    喜洋洋生产了一个包子
    灰太狼吃了包子2
    灰太狼吃了包子3
    灰太狼吃了包子4
    灰太狼吃了包子5
    
    import time
    import random
    from  multiprocessing import JoinableQueue,Process
    def producer(q,name,food):
        for i in range(5):
            time.sleep(random.random())
            fd = '%s%s'%(food,i+1)
            q.put(fd)
            print('%s生产了一个%s'%(name,food))
        q.join()
    def consumer(q,name):
        while True:
            food = q.get()
            time.sleep(random.random())
            print('%s吃了%s'%(name,food))
            q.task_done()
    if __name__ == '__main__':
        jq = JoinableQueue()
        p =Process(target=producer,args=(jq,'喜洋洋','包子'))
        p.start()
        c = Process(target=consumer,args=(jq,'灰太狼'))
        c.daemon = True
        c.start()
        p.join()

    3、二者区别
    1)Queue有多少消费者,就要put多少个None。要在消费者函数添加if 不是真(非None数据)就退出死循环
    2)二者效果一样但是从程序员角度看,joinablequeue更加严谨,更符合编程思维

  • 相关阅读:
    Dev 之 GridControl 列表 显示底部(包括底部统计)
    DEV 之 有些控件不允许拖动。
    Split 之特殊用法
    WebSerivce与WebAPI的区别
    DevExpress的DateEdit设置显示日期和时间
    indexOf 和 lastIndexOf的区别
    DevExpress GridControl使用教程:之 添加 checkbox 复选框
    APP通用测试用例大全
    Windows下搭建easyMock
    Centos8搭建Easy-Mock详细步骤
  • 原文地址:https://www.cnblogs.com/machangwei-8/p/10895554.html
Copyright © 2020-2023  润新知