關(guān)于生產(chǎn)消費(fèi)者模型中task_done()的具體作用
直奔主題
tase_done()的作用:
只有消費(fèi)者把隊(duì)列所有的數(shù)據(jù)處理完畢,queue.join()才會停止阻塞
代碼解釋
#關(guān)于tase_done()的作用:只有消費(fèi)者把隊(duì)列所有的數(shù)據(jù)處理完畢,queue.join()才會停止阻塞 import time from queue import Queue from threading import Thread q = Queue() def produce(): for i in range(10): q.put(i) print('生產(chǎn):',i) print('生產(chǎn)任務(wù)完畢!') q.join() print(produce.__name__,'函數(shù)結(jié)束!') def consumer(): for i in range(10): print('消費(fèi):', q.get()) q.task_done() # if i == 4: # print('休息1s...') # time.sleep(1)#sleep作用:查看生產(chǎn)者是否阻塞 print(consumer.__name__,'函數(shù)結(jié)束!') pro = Thread(target=produce) con = Thread(target=consumer) pro.start() con.start() con.join() print('消費(fèi)者任務(wù)完成') pro.join() print('生產(chǎn)者任務(wù)完成')
生產(chǎn): 0
生產(chǎn): 1
生產(chǎn): 2
生產(chǎn): 3
生產(chǎn): 4
生產(chǎn): 5
消費(fèi): 0
消費(fèi): 1
消費(fèi): 2
消費(fèi): 3
消費(fèi): 4
消費(fèi): 5
生產(chǎn): 6
生產(chǎn): 7
生產(chǎn):8
消費(fèi): 6
消費(fèi): 7
消費(fèi): 8
生產(chǎn): 9
生產(chǎn)任務(wù)完畢!
消費(fèi): 9
consumer 函數(shù)結(jié)束!
produce 函數(shù)結(jié)束!
消費(fèi)者任務(wù)完成
生產(chǎn)者任務(wù)完成
說明:生產(chǎn)任務(wù)已經(jīng)完畢為什么沒有直接produce函數(shù)結(jié)束?
說明這里產(chǎn)生了阻塞,產(chǎn)生阻塞的原因是因?yàn)橄M(fèi)者沒有處理完生產(chǎn)者所有任務(wù)。
tase_done()的作用:只有消費(fèi)者把隊(duì)列所有的數(shù)據(jù)處理完畢,queue.join()才會停止阻塞所以才會有produce函數(shù)結(jié)束!然后生產(chǎn)任務(wù)結(jié)束。
對比解釋看效果
注釋掉q.task_done()和q.join()
#關(guān)于tase_done()的作用:只有消費(fèi)者把隊(duì)列所有的數(shù)據(jù)處理完畢,queue.join()才會停止阻塞 import time from queue import Queue from threading import Thread q = Queue() def produce(): for i in range(10): q.put(i) print('生產(chǎn)任務(wù)完畢!') # q.join() # if i == 4: # print('休息1s...') # time.sleep(1)#sleep作用:查看生產(chǎn)者是否阻塞 print(produce.__name__,'函數(shù)結(jié)束!') def consumer(): for i in range(10): print('消費(fèi):', q.get()) # q.task_done() print(consumer.__name__,'函數(shù)結(jié)束!') pro = Thread(target=produce) con = Thread(target=consumer) pro.start() con.start() con.join() print('消費(fèi)者任務(wù)完成') pro.join() print('生產(chǎn)者任務(wù)完成')
生產(chǎn): 0
生產(chǎn): 1
生產(chǎn): 2
生產(chǎn): 3
生產(chǎn): 4
生產(chǎn): 5
生產(chǎn): 6
生產(chǎn): 7
生產(chǎn): 8
生產(chǎn): 9
消費(fèi): 0
消費(fèi): 1
生產(chǎn)任務(wù)完畢!
produce 函數(shù)結(jié)束!
消費(fèi): 2
消費(fèi): 3
消費(fèi): 4
消費(fèi): 5
消費(fèi): 6
消費(fèi): 7
消費(fèi): 8
消費(fèi): 9
consumer 函數(shù)結(jié)束!
消費(fèi)者任務(wù)完成
生產(chǎn)者任務(wù)完成
說明:不帶task_done()和join()情況下生產(chǎn)任務(wù)結(jié)束,produce函數(shù)立刻結(jié)束,并沒有等待消費(fèi)者處理完所有任務(wù)立即結(jié)束。
僅注釋掉q.task_done()**
#關(guān)于tase_done()的作用:只有消費(fèi)者把隊(duì)列所有的數(shù)據(jù)處理完畢,queue.join()才會停止阻塞 import time from queue import Queue from threading import Thread q = Queue() def produce(): for i in range(10): q.put(i) print('生產(chǎn)任務(wù)完畢!') q.join() print(produce.__name__,'函數(shù)結(jié)束!') def consumer(): for i in range(10): print('消費(fèi):', q.get()) # q.task_done() # if i == 4: # print('休息1s...') # time.sleep(1)#sleep作用:查看生產(chǎn)者是否阻塞 print(consumer.__name__,'函數(shù)結(jié)束!') pro = Thread(target=produce) con = Thread(target=consumer) pro.start() con.start() con.join() print('消費(fèi)者任務(wù)完成') pro.join() print('生產(chǎn)者任務(wù)完成')
生產(chǎn): 0
生產(chǎn): 1
生產(chǎn): 2
生產(chǎn): 3
生產(chǎn): 4
生產(chǎn): 5
生產(chǎn): 6
生產(chǎn): 7
生產(chǎn): 8
生產(chǎn): 9
生產(chǎn)任務(wù)完畢!
消費(fèi): 0
消費(fèi): 1
消費(fèi): 2
消費(fèi): 3
消費(fèi): 4
消費(fèi): 5
消費(fèi): 6
消費(fèi): 7
消費(fèi): 8
消費(fèi): 9
consumer 函數(shù)結(jié)束!
消費(fèi)者任務(wù)完成
。。。阻塞。。。
說明:消費(fèi)者已經(jīng)把任務(wù)完成了,但是produce函數(shù)卻一直阻塞沒有結(jié)束。
總結(jié)
通過以上分析可以得出結(jié)論:
task_done()的作用:消費(fèi)者處理一個任務(wù),它就通知生產(chǎn)者我處理了一個任務(wù)。
為什么要告訴生產(chǎn)者消費(fèi)者處理了一個任務(wù)呢?
這也是為什么我進(jìn)行注釋對比的原因
- 1.注釋q.task_done(),不注釋q.join(),我們發(fā)現(xiàn)produce函數(shù)一直阻塞沒有結(jié)束。
- 2.注釋q.task_done(),注釋q.join(),我們發(fā)現(xiàn)生產(chǎn)者生產(chǎn)完任務(wù)produce函數(shù)就結(jié)束了,而不是等到消費(fèi)者消費(fèi)完才結(jié)束。這沒有task_done和join:這個模型一定是生產(chǎn)者先生產(chǎn)任務(wù),消費(fèi)者發(fā)現(xiàn)有任務(wù)就消費(fèi)(不然會阻塞等待),所以一定是生產(chǎn)者生產(chǎn)完后就馬上結(jié)束生產(chǎn)而消費(fèi)者還沒有結(jié)束。
- 3.不注釋q.task_done(),不注釋q.join(),我們發(fā)現(xiàn)produce函數(shù)在消費(fèi)者消費(fèi)完后才結(jié)束,而不是生產(chǎn)完就結(jié)束。
生產(chǎn)者如果被消費(fèi)者的task_done()告知沒有把生產(chǎn)者交給的任務(wù)處理完畢,那么生產(chǎn)者就會一直阻塞(生氣…)。
大家可以把sleep()函數(shù)的注釋刪掉看看,并且設(shè)置任意一個sleep()時間觀察現(xiàn)象。
如果只有q.join()而沒有task_done(),消費(fèi)者處理完所有任務(wù),生產(chǎn)者任然阻塞,所以q.join()一般和q.task_done()配合使用。
最后
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
將Jupyter?Notebook(.ipynb)文件轉(zhuǎn)換為Python(.py)文件的3種方法
大多數(shù)數(shù)據(jù)科學(xué)在線課程都把Jupyter Notebook作為教學(xué)媒介,這是因?yàn)槌鯇W(xué)者在Jupyter Notebook的單元格中編寫代碼,比編寫包含類和函數(shù)的腳本更容易,這篇文章主要給大家介紹了關(guān)于將Jupyter?Notebook(.ipynb)文件轉(zhuǎn)換為Python(.py)文件的3種方法,需要的朋友可以參考下2023-10-10Python字符串本身作為bytes進(jìn)行解碼的問題
這篇文章主要介紹了解決Python字符串本身作為bytes進(jìn)行解碼的問題,文末給大家補(bǔ)充介紹了,Python字符串如何轉(zhuǎn)為bytes對象?Python字符串和bytes類型怎么互轉(zhuǎn),需要的朋友可以參考下2022-11-11Python正則表達(dá)式如何進(jìn)行字符串替換實(shí)例
Python正則表達(dá)式在使用中會經(jīng)常應(yīng)用到字符串替換的代碼。這篇文章主要介紹了Python正則表達(dá)式如何進(jìn)行字符串替換,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-12-12Python 圖片轉(zhuǎn)數(shù)組,二進(jìn)制互轉(zhuǎn)操作
這篇文章主要介紹了Python 圖片轉(zhuǎn)數(shù)組,二進(jìn)制互轉(zhuǎn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03python中通過pip安裝庫文件時出現(xiàn)“EnvironmentError: [WinError 5] 拒絕訪問”的問題
這篇文章主要介紹了python中通過pip安裝庫文件時出現(xiàn)“EnvironmentError: [WinError 5] 拒絕訪問”的問題,本文給大家分享解決方案,感興趣的朋友跟隨小編一起看看吧2020-08-08詳解Python中Pytest和Unittest的區(qū)別
Pytest?和?Unittest是Python中屬于最常用的兩個測試框架。那么他們有些什么區(qū)別呢??Playwright?為什么只給了Pytest的深度支持,而不是Unittest呢?本文就來和大家詳細(xì)聊聊2023-03-03