實現生產者與消費者模式
實現生產者與消費者模式
目錄
生產者與消費者模式 實現
生產者與消費者模式
什麼是生產者消費者模式
生產者消費者模式是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通訊,而通過阻塞佇列來進行通訊,所以生產者生產完資料之後不用等待消費者處理,直接扔給阻塞佇列,消費者不找生產者要資料,而是直接從阻塞佇列裡取,阻塞佇列就相當於一個緩衝區,平衡了生產者和消費者的處理能力。
這個阻塞佇列就是用來給生產者和消費者解耦的。縱觀大多數設計模式,都會找一個第三者出來進行解耦,如工廠模式的第三者是工廠類,模板模式的第三者是模板類。在學習一些設計模式的過程中,如果先找到這個模式的第三者,能幫助我們快速熟悉一個設計模式。
為什麼要使用生產者消費者模式
主要是為了解耦與併發
解耦
假設生產者和消費者分別是兩個類。如果讓生產者直接呼叫消費者的某個方法,那麼生產者對於消費者就會產生依賴(也就是耦合)。將來如果消費者的程式碼發生變化,可能會影響到生產者。而如果兩者都依賴於某個緩衝區,兩者之間不直接依賴,耦合也就相應降低了。
支援併發
線上程的世界裡,生產者就是生產資料的執行緒,消費者就是消費資料的執行緒,在多執行緒開發中,如果生產者處理速度很快,而消費者的速度很慢,那麼生產者就必須等待消費者處理完,才能繼續生產資料。同樣的道理,如果消費者的處理能力大於生產者,那麼消費者就必須等待生產者。
生產者直接呼叫消費者的某個方法,還有另一個弊端。由於函式呼叫是同步的(或者叫阻塞的),在消費者的方法沒有返回之前,生產者只好一直等在那邊。萬一消費者處理資料很慢,生產者就會白白糟蹋大好時光。
使用了生產者/消費者模式之後,生產者和消費者可以是兩個獨立的併發主體(常見併發型別有程序和執行緒兩種,後面的帖子會講兩種併發型別下的應用)。生產者把製造出來的資料往緩衝區一丟,就可以再去生產下一個資料。基本上不用依賴消費者的處理速度。
生產者消費者模式標準
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()
演示結果: