zoukankan      html  css  js  c++  java
  • 实现生产者与消费者模式

    实现生产者与消费者模式

    目录

    生产者与消费者模式
    实现

     

    生产者与消费者模式

    什么是生产者消费者模式

    生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

    这个阻塞队列就是用来给生产者和消费者解耦的。纵观大多数设计模式,都会找一个第三者出来进行解耦,如工厂模式的第三者是工厂类,模板模式的第三者是模板类。在学习一些设计模式的过程中,如果先找到这个模式的第三者,能帮助我们快速熟悉一个设计模式。

     

     为什么要使用生产者消费者模式

     主要是为了解耦与并发

    解耦
    假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。将来如果消费者的代码发生变化,可能会影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合也就相应降低了。

    支持并发
    在线程的世界里,生产者就是生产数据的线程,消费者就是消费数据的线程,在多线程开发中,如果生产者处理速度很快,而消费者的速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。

    生产者直接调用消费者的某个方法,还有另一个弊端。由于函数调用是同步的(或者叫阻塞的),在消费者的方法没有返回之前,生产者只好一直等在那边。万一消费者处理数据很慢,生产者就会白白糟蹋大好时光。

    使用了生产者/消费者模式之后,生产者和消费者可以是两个独立的并发主体(常见并发类型有进程和线程两种,后面的帖子会讲两种并发类型下的应用)。生产者把制造出来的数据往缓冲区一丢,就可以再去生产下一个数据。基本上不用依赖消费者的处理速度。

     

     

    生产者消费者模式标准

    1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
    2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
    3、当消费者发现仓储没产品可消费时候会通知生产者生产。
    4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费。

    实现

    这里只是简单实现了

    消费者仅仅在仓储有产品时候才能消费,仓空则等待

    生产者在生产出可消费产品时候,应该通知等待的消费者去消费

    q.task_done()与q.join()实现了这两个功能。

    Producter方法:生产者制造数据

    q.put()方法:相当于生产者把数据放入缓冲区

    q.put()方法:相当于消费者把数据取出缓存区

    Comsumer方法:消费者处理数据

    程序示例

    import time
    import queue,threading
    
    q=queue.Queue()
    
    
    #生产者
    def Producter(name):
    
        n=1
        while 1:
            time.sleep(1)
            print('已经生产出来%d个包子' % (n))
            # 将数据发给队列
            q.put(n)
            n+=1
            #通知队列,这里是通知队列已经发完数据
            q.task_done()
    
    
    #消费者
    def Comsumer(name):
        while 1:
            time.sleep(1)
            # 等待接收到通知才继续往下执行
            print('%s在等待包子' %name)
            q.join()
            #从队列里面取值
            count = q.get()
            print('%s吃到第%d个包子' % (name, count))
    
    
    
    c1=threading.Thread(target=Producter,args=('C'))
    p1=threading.Thread(target=Comsumer,args=('A'))
    p2=threading.Thread(target=Comsumer,args=('B'))
    
    c1.start()
    p1.start()
    p2.start()
    

      

    演示结果

     

  • 相关阅读:
    winform combobox SelectedText值为空
    【转】C#、面向对象、设计模式学习
    oracle查询分区表中的数据
    ORA-14402:更新分区关键字列将导致分区更改
    winform列标题高度无法改变
    【转】c#中@的3种作用
    winform 弹出的form显示在最前端
    winform datagridview数据显示不全
    【转】如何把CD上的音乐拷贝到电脑上
    开关WIFI脚本
  • 原文地址:https://www.cnblogs.com/-wenli/p/10331220.html
Copyright © 2011-2022 走看看