浅谈 Python 中的多线程。
本文作者:Rocky0249
公眾號:Python空間
00.寫在之前
大家好,我是 Rocky0429,今天我來寫一下 Python 中的多線程。在正式開始之前,我先用比較通俗的語言給大家介紹幾個比較重要的概念。
首先是「并發(fā)編程」。「并發(fā)」其實在我們的生活中隨處可見,比如我們?nèi)ャy行存錢,銀行如果只有一個窗口并且辦業(yè)務(wù)的人又比較多,那么肯定就是排成一個長長的隊伍,這樣的體驗對我們來說肯定是非常差的。那么該如何解決這個問題呢?那就是多開幾個窗口,把人流分散開,這樣就減短了我們隊伍的長度,減少整體排隊的時間。
上面是我們顯示生活中遇到的問題,其實在計算機中我們也會遇到這樣的問題,那么我們是怎么解決的呢?其實是這樣,每次我們運行一個 Python 程序,這個運行中的程序我們稱它為「進程」,如果我們想讓它快一點,能夠像我們上面例子中多開幾個窗口并發(fā)解決問題一樣,我們就要在進程里引入一個更小的東西,那就是「線程」。
我來舉一個具體的例子,比如我們每天都會用的微信,每次運行它的時候會產(chǎn)生一個進程,估計大家都碰到過這種情況,就是你在和別人開視頻的時候,另外有一個人給你發(fā)消息,我們都知道這個時候可以把視頻的窗口縮小然后回復(fù)另一個人的消息,能完成這樣的操作,其實就是微信里的多個線程幫助我們完成了這件事。
在編寫 Python 程序的時候我們也會遇到這種“同時”的需求,同時有大量的請求過來,要我們同時對它們進行處理,那么這個處理的方法,就是「多線程」編程。
01.創(chuàng)建「線程」
Python 的標準庫中自帶了多線程相關(guān)的模塊,使在 python 中創(chuàng)建線程成了一件很簡單的事。與線程相關(guān)的模塊一共有兩個:thread 和 threading。一般情況下我們只需要 threading 即可。
下面我來寫一個簡單的使用多線程的例子:
def func(): print('Hello World')
def main():????for?i?in?range(4): t = threading.Thread(target=func) t.start()
if __name__ == '__main__': main()
上面的代碼中,我定義了一個 func 函數(shù),然后在 main 函數(shù)中通過 for 循環(huán)創(chuàng)建了 4 個線程,然后通過將 target = func 的方式去告訴線程執(zhí)行 func 函數(shù),一切就緒后調(diào)用線程的 start 方法運行線程。結(jié)果如下:
這個結(jié)果看起來和我們直接用 for 循環(huán)打印四次 Hello World 沒什么區(qū)別,其實區(qū)別還是有的,就是肉眼看不出來而已,下面我來改造一下上面的程序:
def func(): print('Hello World') time.sleep(1)
def main(): for i in range(4): t = threading.Thread(target=func) t.start()
if __name__ == '__main__': main()
上面我加了 time.sleep(1),如果只是用 for 循環(huán)的話,這個程序至少得運行 4 秒,但是由于我們用的是線程并發(fā)運行,其實整個程序只需要花費 1 秒多就可以運行完畢,你可以自行嘗試一下,可以 sleep 的時間長點自行體驗一下。
當然了,如果你自己不樂意動手,作為關(guān)愛讀者成長協(xié)會的會長,我這還有一個好的辦法,且待我再改造一下:
def func(): print(current_thread().getName(),'start') print('Hello World') time.sleep(1) print(current_thread().getName(), 'end')
def main(): for i in range(4): t = threading.Thread(target=func) t.start()
if __name__ == '__main__': main()
上面的改造中引用了 current_thread,對當前運行狀態(tài)進行一個顯示,你可以很好的看到線程在運行中的一些過程,運行結(jié)果如下所示:
02.線程傳參
在上面創(chuàng)建線程的例子其實是過于簡單了,在我們實際的編程中給程序傳遞參數(shù)是必不可少的,下面我在之前例子的基礎(chǔ)上,寫一個傳遞參數(shù)的例子:
def func(cnt, name): for i in range(cnt): print('Hello {}'.format(name))
def main(): names = ['Rocky', 'leey', 'cp3', 'chen'] for i in range(4): t = threading.Thread(target=func, args=(10, names[i])) t.start()
if __name__ == '__main__': main()
上面的程序中,我讓 func 接受了兩個參數(shù),在 main 函數(shù)中定義了一個 names 的列表,之后在創(chuàng)建線程的時候?qū)?names 中的元素傳遞給不同的線程。由上可以看出在 Python 中線程傳遞參數(shù)也是一件很簡單的事,傳遞的參數(shù)都是調(diào)用 args,通過元組的形式進行。
03.寫在之后
其實很多人認為 Python 的多線程是一個相當“雞肋”的東西,因為標準的 Python 系統(tǒng)中使用了 GIL(全局解釋器鎖),它的作用是避免 Python 解釋器中的線程問題,這樣造成了在任意時刻只有一個線程在執(zhí)行 Python 代碼,這樣就“糟蹋”了計算機「多核」的特性。
誠然,“糟蹋”了多核,這樣對 CPU 密集型的程序來說,Python 多線程確實沒有什么提升,反而會更慢,但我們的程序其實也不是無時無刻在“動彈”的,它們也要等待資源的下載,等待文件的讀寫,等待用戶的輸入等等等等,這類操作我們統(tǒng)一稱為 I/O 操作,對于這類,才是真正顯示 Python 多線程能力的時候。
所以,也不是太“雞肋”嘛。
?長按二維碼可以關(guān)注噢
總結(jié)
以上是生活随笔為你收集整理的浅谈 Python 中的多线程。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习必学10大算法
- 下一篇: 包邮送 36 本书,已全部打包好!