zoukankan      html  css  js  c++  java
  • Python并发编程-生产消费模型

    生产消费模型初步

    #产生两个子进程,Queue可以在子进程之间传递消息
    from multiprocessing import Queue,Process
    import random
    import time
    #队列是进程安全的,队列里的数据只能被一个进程获取,所有q.put(None)只对应一个进程,所以要放两个q.put(None)
    def producer(name, food, q):
        for i in range(10):
            time.sleep(random.randint(1,3))
            f = ('%s生产了%s%s' %(name,food,i))
            print(f)
            q.put(f)
    def consume(q,name):
        while True:
            food = q.get()
            if food is None:
                print('%s获取了个一个空'%name)
                break
            print('33[31m%s消费了%s33[0m' % (name, food))
            time.sleep(random.randint(1,3))
    
    if __name__ == '__main__':
        q = Queue(20) #Queue可以在进程间传递数据
        p = Process(target=producer, args=('Egon','包子',q))
        p2 = Process(target=producer, args=('WuSir', '泔水', q))
        p.start()
        p2.start()
        c = Process(target=consume, args=(q,'Alex'))
        c2 = Process(target=consume, args=(q,'jinboss'))
        c.start()
        c2.start()
        p.join()#使得主进程感知P,P2的结束
        p2.join()
        q.put(None)
        q.put(None)
    

    利用JoinableQueue改进生产消费模型

    • 前一版的主要问题是不知道生产者和消费者的数量不可确定
    #产生两个子进程,Queue可以在子进程之间传递消息
    from multiprocessing import Process, JoinableQueue
    import random
    import time
    #队列是进程安全的,队列里的数据只能被一个进程获取,所有q.put(None)只对应一个进程,所以要放两个q.put(None)
    def producer(name, food, q):
        for i in range(10):
            time.sleep(random.randint(1,3))
            f = ('%s生产了%s%s' %(name,food,i))
            print(f)
            q.put(f)
        q.join() #感知一个队列中的数据全部被执行完毕,阻塞,直至所有数据处理完毕
                #增加了join后,生产者得等到消费者把生产的数据都消费了才结束
    def consume(q,name):
        while True:
            food = q.get()
            if food is None:
                print('%s获取了个一个空'%name)
                break
            print('33[31m%s消费了%s33[0m' % (name, food))
            time.sleep(random.randint(1,3))
            q.task_done() #提交取出数据已完成的信号, count-1
    
    if __name__ == '__main__':
        q = JoinableQueue(20) #Queue可以在进程间传递数据
        p = Process(target=producer, args=('Egon','包子',q))
        p2 = Process(target=producer, args=('WuSir', '泔水', q))
        p.start()
        p2.start()
        c = Process(target=consume, args=(q,'Alex'))
        c2 = Process(target=consume, args=(q,'jinboss'))
        c.daemon = True #关键步骤
        c2.daemon = True #主进程中代码执行完毕之后,会自动结束,这两个守护进程会随着
                        #p,p2的进程的结束而结束
        c.start()
        c2.start()
        p.join()#主进程感知P,P2的结束
        p2.join()
        # q.put(None)
        # q.put(None)
    
    #首先在消费者这端:
        # 每次获取一个数据
        # 处理一个数据
        # 发送一个记号:标志一个数据被处理成功
    
    #在生产者这一端:
        # 每一次生产一个数据
        # 且每一次生产的数据都放在队列中
        # 在队列中刻上一个记号
        # 当生产者全部生产完毕之后
        # 发送Join信号,标志着生产者已经停止生产数据了, 且要等待之前被刻上记号的数据都被消费完
        # 当数据都被处理完是, join阻塞结束
        
    #consumer中把所有的任务消耗完
    #producer端的join感知到,停止阻塞
    #所有的producer进程结束
    #主进程的P.join结束
    #主进程代码结束
    #守护进程(消费者进程)跟着结束
    
  • 相关阅读:
    如何保证 Redis 缓存与数据库双写一致性?
    如何合理地估算线程池大小?
    不用装工具,一条 Linux 命令就能实现文件上传下载!
    看了 Google 大神 Jeff Dean 的传说,我拜服了~
    div设置水平垂直居中
    "起用"与"启用"
    徇私舞弊
    精选排比金句20例
    一笔画图推
    一笔画
  • 原文地址:https://www.cnblogs.com/konglinqingfeng/p/9693736.html
Copyright © 2011-2022 走看看