使用隊列queue實現一個簡單的生產者消費者模型
我們去超市商店等地購買商品時,我們大部分人都會說自己是消費者,而超市的各大供貨商、工廠等,自然而然地也就成了我們的生產者。如此一來,生產者有了,消費者也有了,那麽將二者聯系起來的超市又該作何理解呢?誠然,它本身是作為一座交易場所而誕生。
上述情形類比到實際的軟件開發過程中,經常會發現:某個線程或模塊的代碼負責生產數據(工廠),而生產出來的數據卻不得不交給另一模塊(消費者)來對其進行處理,在這之間使用了隊列、棧等類似超市的東西來存儲數據(超市),這就抽象除了我們的生產者/消費者模型。
其中,產生數據的模塊,就形象地稱為生產者;而處理數據的模塊,就稱為消費者;生產者和消費者之間的中介就叫做緩沖區。
在來一個列子:
我們在使用QQ, 微信通信過程,或者郵件
- 我們寫信、寫消息,然後將消息發送過去, ---相當於生產者,發布消息
-中 間QQ、微信、郵件服務器收到數據(等於緩沖區), ---相當於緩沖區,隊列queue等 - 然後收消息的人上線,從服務端取出消息,郵件,去辦理相關的業務 ----相當於消費者處理數據
生產者消費者模式就是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通訊,而通過阻塞隊列來進行通訊,所以生產者生產完數據之後不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產者要數據,而是直接從阻塞隊列裏取,阻塞隊列就相當於一個緩沖區,平衡了生產者和消費者的處理能力。這個阻塞隊列就是用來給生產者和消費者解耦的。
在線程世界裏,生產者就是生產數據的線程,消費者就是消費數據的線程。在多線程開發當中,如果生產者處理速度很快,而消費者處理速度很慢,那麽生產者就必須等待消費者處理完,才能繼續生產數據。同樣的道理,如果消費者的處理能力大於生產者,那麽消費者就必須等待生產者。為了解決這種生產消費能力不均衡的問題,所以便有了生產者和消費者模式。
優點:
解耦,即降低生產者和消費者之間的依賴關系。
比如我們在修改消費者功能時,不需要考慮生產者模塊的代碼,同理對於生產者支持並發,即生產者和消費者可以是兩個獨立的並發主體,互不幹擾的運行。
在生產者和消費者之間,因為是通過隊列通訊,互不幹擾,所以可以起兩個線程,各自完成自己的工作支持忙閑不均,如果制造數據的速度時快時慢,緩沖區可以對其進行適當緩沖。當數據制造快的時候,消費者來不及處理,未處理的數據可以暫時存在緩沖區中。等生產者的制造速度慢下來,消費者再慢慢處理掉。
import threading
import queue
import time
q= queue.Queue(10)
def producer(worker,q):
count = 0
while True:
if not q.full():
q.put(count)
print('[{}] 生產了 {}'.format(worker, count))
count += 1
time.sleep(0.3)
def consumer(name, q):
while True:
print('{} 消費了 {}'.format(name, q.get()))
time.sleep(1)
if q.qsize() == 0:
break
p1 = threading.Thread(target= producer, args= ('lina', q))
c1 = threading.Thread(target= consumer, args= ('david', q))
c2 = threading.Thread(target= consumer, args= ('sven', q))
p1.start()
c1.start()
c2.start()
#執行結果為
[lina] 生產了 0
david 消費了 0
[lina] 生產了 1
sven 消費了 1
[lina] 生產了 2
[lina] 生產了 3
david 消費了 2
[lina] 生產了 4
sven 消費了 3
[lina] 生產了 5
[lina] 生產了 6
david 消費了 4
[lina] 生產了 7
使用隊列queue實現一個簡單的生產者消費者模型