在使用queue模組+多執行緒模擬生產者+消費者問題時,遇到了乙個小問題,現在記錄下來。供可能會遇到類似問題的初學者們參考。
該問題的完整參考**如下。主要實現了以下的功能:在乙個執行緒中,開啟生產者模式,生成出來的object會put進乙個queue物件queue中。除此以外,在n個執行緒中(本**中n為5,nfuncs = 5),開啟消費者模式,每乙個消費者執行緒會在乙個while迴圈中不斷地從queue中消耗乙個object(使用get方法),直到生產者生產出的object被全部消耗(本**中設為100個object)。
from random import randint
from time import sleep
from queue import queue
from threading import thread,lock,currentthread
lock = lock()
def writes(queue):
print "producing object for q...",
queue.put('***', 1)
print "size now", queue.qsize()
def readq(queue):
val = queue.get(1)
print "consumed object from q... size now", \
queue.qsize()
print currentthread().name
def writer(queue, loops):
for i in range(loops):
lock.acquire()
writes(queue)
lock.release()
sleep(0.1)
def read(queue):
while queue.qsize() >0 :
sleep(randint(2, 4))
lock.acquire()
readq(queue)
lock.release()
funcs = [writer, read]
nfuncs = range(5)
def main():
nloops1 = 100
q = queue(1024)
thread =
t = thread(target = writer, args = (q, nloops1))
for i in nfuncs:
t = thread(target = read, args = (q,))
for i in range(len(thread)):
thread[i].start()
for i in range(len(thread)):
thread[i].join()
print "all done"
if __name__ == '__main__':
main()
為了防止生產速度跟不上消費的速度,生產線程中每次生產僅間隔0.1秒,且在消費執行緒中每次消費之前,隨機sleep 2~3秒。
在執行之後,生產的object數量達到100(實際不會print 100號object的生成,因為在生產的過程中已經開始消費),然後多個執行緒開始消費。然而在把object數量消費至0以後,執行緒們並不會結束,既「print 「」all done「」」語句一直沒有被執行。
思考以後,得出了三種解決途徑:
2.試圖考慮為什麼執行緒會阻塞。
發現在read函式中,如前所述,在每次消費之前,隨機sleep 2~3秒。於是可能會出現以下的問題。
當 queue.qsize() = 1的時候,某個執行緒x進入了while迴圈,然後開始睡眠2~3秒,在這個睡眠過程中,gui切換至其它的執行緒,此時由於執行緒x處於睡眠,並沒有呼叫readq函式,因此queue中仍然有乙個元素。以此類推,每個程序都在queue.qsize() = 1時進入了while迴圈,然後最早結束睡眠的執行緒將呼叫readq函式中的queue.get(1)。之後其它程序在呼叫queue.get(1)時,將會因為queue中缺少元素阻塞。
解決方法如下:
def read(queue):
sleep(randint(2, 4))
while queue.qsize():
lock.acquire()
readq(queue)
lock.release()
sleep(randint(2, 4))
在while之前睡眠,且將每次消費時所需的睡眠放至readq函式之後。可避免多個執行緒同時進入while迴圈,該改進將不會
引起阻塞。
3.queue中的get方法,若將其引數設定為非0,則不會因為佇列中沒有可用元素而阻塞。將get的引數設定為0,
利用try/excep語句,
當get不到資料引起異常時,excep乙個break,中斷執行緒。
多執行緒 阻塞佇列
blockingqueue最終會有四種狀況,丟擲異常 返回特殊值 阻塞 超時,下表總結了這些方法 丟擲異常 特殊值阻塞 超時插入add e offer e put e offer e,time,unit 移除remove poll take poll time,unit 檢查element peek...
多執行緒 阻塞佇列
1 當佇列滿的時候,插入元素的執行緒被阻塞,直達佇列不滿。2 隊列為空的時候,獲取元素的執行緒被阻塞,直到佇列不空。生產者就是生產資料的執行緒,消費者就是消費資料的執行緒。在多執行緒開發中,如果生產者處理速度很快,而消費者處理速度很慢,那麼生產者就必須等待消費者處理完,才能繼續生產資料。同樣的道理,...
python中多執行緒 Python之多執行緒
python之多執行緒 一 概念 1 多工可以由多程序完成,也可以由乙個程序內的多執行緒完成。程序是由若干的執行緒組成,乙個程序至少有乙個程序。執行緒是作業系統直接支援的執行單元,天賜高階預壓通常都是內建多執行緒的支援,python的執行緒是真正的posix thread而不是模擬出來的執行緒。2 ...