淺析Python中線程以及線程阻塞
本文所依賴的環(huán)境為:
進(jìn)程和線程的概念
進(jìn)程概念
我們想運(yùn)行一個(gè)程序,首先會(huì)將該程序從存儲(chǔ)介質(zhì)上通過IO
總線加載進(jìn)內(nèi)存中,而后再通過cpu
進(jìn)行調(diào)度。這個(gè)時(shí)候,我么么將這個(gè)正在運(yùn)行的程序稱之為進(jìn)程,它有內(nèi)存地址、內(nèi)存空間、數(shù)據(jù)棧等等信息,進(jìn)程之間通信一般稱之為IPC
,常見的方法有 管道、消息隊(duì)列、套接字等。
線程概念
而線程則不同,線程是在進(jìn)程中運(yùn)行的,一個(gè)進(jìn)程至少有一個(gè)線程。在單個(gè)cpu
中,同一時(shí)刻一個(gè)進(jìn)程只有一個(gè)線程在工作,其他則被掛起,也稱之為睡眠。由于線程屬于進(jìn)程,所以會(huì)共享進(jìn)程的內(nèi)存信息。線程之間通信不僅可以使用共享內(nèi)存來通信,依然可以使用 如 管道、消息隊(duì)列、套接字等。
線程優(yōu)缺點(diǎn)
多線程是一種并發(fā)方式,優(yōu)點(diǎn)為可以同時(shí)執(zhí)行多個(gè)任務(wù),用于提升時(shí)間和效率。
比如,我們想寫一個(gè)python
服務(wù)器下載電影,一次只能下載一部,若我們使用多線程后,可以一次"同時(shí)"下載n
部,從而提升了效率。
但是有些事多線程不能做的,并發(fā)沖突是其中一種。比如掘金點(diǎn)贊功能,如果沒有對(duì)點(diǎn)贊這個(gè)變量進(jìn)行并發(fā)控制,可能會(huì)出現(xiàn)數(shù)據(jù)不一致的情況。
在python中如何使用線程
在使用python
寫多線程之前,先來看一個(gè)小案例,假設(shè)我們使用python
寫了一個(gè)下載電影的程序。
import time def downloadMovie(i): print("%s 開始下載編號(hào)為%s電影中。。。" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), str(i))) time.sleep(5) print("%s 編號(hào)為%s電影下載完畢" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), str(i))) def main(): for i in range(5): downloadMovie(i) if __name__ == '__main__': main()
我們假設(shè)模擬下載電影的一個(gè)程序,下載過程使用time.sleep
代替。在沒有使用多線程的時(shí)候,它的執(zhí)行過程如下:
可以看到,它是順序執(zhí)行的,需要等上一部下載完畢,才能開始下載下一部。
如果使用線程來做該需求呢? 我們可以這樣來寫:
import time import threading def downloadMovie(i): print("%s 開始下載編號(hào)為%s電影中。。。" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), str(i))) time.sleep(5) print("%s 編號(hào)為%s電影下載完畢" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), str(i))) def main(): for i in range(5): t = threading.Thread(target=downloadMovie,args=(i,)) t.start() if __name__ == '__main__': main()
上述代碼,在原始代碼基礎(chǔ)上,我們引入了threading
庫(kù),在循環(huán)中使用Thread
來做線程的實(shí)例化對(duì)象,我們需要傳入target
和args
,target
需要傳入函數(shù)名稱,args
需要傳入?yún)?shù),注意這里參數(shù)需要傳入可迭代的對(duì)象,所以當(dāng)只有一個(gè)參數(shù)的時(shí)候,也需要在后面加一個(gè),
。最后使用start
方法讓其開始執(zhí)行。
運(yùn)行后的效果如下:
可以發(fā)現(xiàn),我們程序幾乎同步的打印下載開始,也幾乎同時(shí)打印下載完畢。
總結(jié)起來發(fā)現(xiàn),我們線程啟動(dòng)一個(gè)線程,是不是非常簡(jiǎn)單呢?只需要引入threading
模塊,定義Thread
來做對(duì)象,最后使用start()
運(yùn)行即可。
線程阻塞也很重要
線程直接跑就完了唄,為什么還需要阻塞呢?我們這里做一個(gè)簡(jiǎn)單的需求:上面的代碼改改,我們下載完視頻后,要壓縮一下,由于只討論線程,所以就只用print
代替操作,我們可以這樣操作:
在上面的基礎(chǔ)上,我們?cè)黾恿?個(gè)步驟,1: 是將下載好的文件放入列表fileList
中,2. 最后開始遍歷fileList
文件,進(jìn)行壓縮,最后打印一個(gè)壓縮完畢,看起來沒什么問題吧?
那我們來運(yùn)行一下一下呢?
額。。。這個(gè)很顯然不符合我們的預(yù)期,我們還沒下載文件完畢,怎么就開始?jí)嚎s了呢,而且壓縮完畢了,再輸出的文件下載完畢,這是為什么呢?
這是因?yàn)榫€程在啟動(dòng)后,如果我們不去設(shè)置阻塞,他就會(huì)一直執(zhí)行下去,就拿我們剛才的案例來看,我們可以將其理解為:
看上圖,我們啟動(dòng)線程后,它就放在后臺(tái)了,我們就立馬執(zhí)行遍歷fileList
步驟,但是這個(gè)時(shí)候恰恰fileList
是空的,所以我們壓縮了空文件,壓縮完畢后,文件才下載完畢。
這個(gè)時(shí)候我們就需要等線程執(zhí)行完畢之后,再執(zhí)行下面的語句了,否則執(zhí)行完了沒意義,所以這個(gè)時(shí)候就需要引入線程阻塞了,我們需要將下載的線程全部執(zhí)行完畢后,再開始?jí)嚎s文件,只需要線程增加一個(gè)join
方法即可,代碼修改如下:
在原先的基礎(chǔ)上,我們需要先定義一個(gè)線程池,用于放已經(jīng)執(zhí)行了的線程,而后再遍歷該線程池,每一個(gè)都設(shè)置阻塞,這樣就會(huì)等所有線程都執(zhí)行完畢了,再進(jìn)行后面的操作,由于我們后面是壓縮需要用到前面的結(jié)果,所以阻塞是必不可少的,程序執(zhí)行結(jié)果為:
這個(gè)流程圖可以理解為這樣的:
現(xiàn)在你知道阻塞有什么用了吧。
總結(jié)
今天介紹了一下python
的多線程,這里只是簡(jiǎn)單的使用threading
庫(kù),在python
中,多線程的庫(kù)不僅于此,還有thread
、Queue
等。最后舉了一個(gè)很簡(jiǎn)單的例子來說明線程阻塞的重要性。
以上就是淺析Python中線程以及線程阻塞的詳細(xì)內(nèi)容,更多關(guān)于Python線程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
從零學(xué)python系列之從文件讀取和保存數(shù)據(jù)
在Python一般都是運(yùn)用內(nèi)置函數(shù)open()與文件進(jìn)行交互,下面說說具體用法2014-05-05pygame實(shí)現(xiàn)方塊動(dòng)畫實(shí)例講解
在本篇文章里小編給大家整理的是一篇關(guān)于pygame實(shí)現(xiàn)方塊動(dòng)畫實(shí)例講解內(nèi)容,以后需要的朋友們可以學(xué)習(xí)參考下。2021-12-12Python中使用NumPy進(jìn)行數(shù)據(jù)處理方式
這篇文章主要介紹了Python中使用NumPy進(jìn)行數(shù)據(jù)處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02python GUI庫(kù)圖形界面開發(fā)之PyQt5控件數(shù)據(jù)拖曳Drag與Drop詳細(xì)使用方法與實(shí)例
這篇文章主要介紹了python GUI庫(kù)圖形界面開發(fā)之PyQt5控件數(shù)據(jù)拖曳Drag與Drop詳細(xì)使用方法與實(shí)例,需要的朋友可以參考下2020-02-02python pygame實(shí)現(xiàn)擋板彈球游戲
這篇文章主要為大家詳細(xì)介紹了python pygame實(shí)現(xiàn)擋板彈球游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11python之pyinstaller組件打包命令和異常解析實(shí)戰(zhàn)
前段時(shí)間在制作小工具的時(shí)候,直接在命令行用pyinstaller工具打包成功后,啟動(dòng)exe可執(zhí)行文件的時(shí)候各種報(bào)錯(cuò), 今天,我們就分享一下踩坑經(jīng)過,需要的朋友可以參考下2021-09-09