1. 程式人生 > >實現生產者與消費者模式

實現生產者與消費者模式

產品 style 等待 pytho ask 緩沖 制造 目錄 tex

實現生產者與消費者模式

目錄

生產者與消費者模式
實現

生產者與消費者模式

什麽是生產者消費者模式

生產者消費者模式是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通訊,而通過阻塞隊列來進行通訊,所以生產者生產完數據之後不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產者要數據,而是直接從阻塞隊列裏取,阻塞隊列就相當於一個緩沖區,平衡了生產者和消費者的處理能力。

這個阻塞隊列就是用來給生產者和消費者解耦的。縱觀大多數設計模式,都會找一個第三者出來進行解耦,如工廠模式的第三者是工廠類,模板模式的第三者是模板類。在學習一些設計模式的過程中,如果先找到這個模式的第三者,能幫助我們快速熟悉一個設計模式。

技術分享圖片

為什麽要使用生產者消費者模式

主要是為了解耦與並發

解耦
假設生產者和消費者分別是兩個類。如果讓生產者直接調用消費者的某個方法,那麽生產者對於消費者就會產生依賴(也就是耦合)。將來如果消費者的代碼發生變化,可能會影響到生產者。而如果兩者都依賴於某個緩沖區,兩者之間不直接依賴,耦合也就相應降低了。

支持並發
在線程的世界裏,生產者就是生產數據的線程,消費者就是消費數據的線程,在多線程開發中,如果生產者處理速度很快,而消費者的速度很慢,那麽生產者就必須等待消費者處理完,才能繼續生產數據。同樣的道理,如果消費者的處理能力大於生產者,那麽消費者就必須等待生產者。

生產者直接調用消費者的某個方法,還有另一個弊端。由於函數調用是同步的(或者叫阻塞的),在消費者的方法沒有返回之前,生產者只好一直等在那邊。萬一消費者處理數據很慢,生產者就會白白糟蹋大好時光。

使用了生產者/消費者模式之後,生產者和消費者可以是兩個獨立的並發主體(常見並發類型有進程和線程兩種,後面的帖子會講兩種並發類型下的應用)。生產者把制造出來的數據往緩沖區一丟,就可以再去生產下一個數據。基本上不用依賴消費者的處理速度。

生產者消費者模式標準

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()

  

演示結果

技術分享圖片

實現生產者與消費者模式