文章插圖

文章插圖
前言
大家好,我是星期八 。
我們都知道,不管是Java,還是C++,還是Go,還是Python,都是有線程這個概念的 。
但是我們知道,線程是不能隨便創建的,就像每招一個員工一樣,是有代價的,無限制招人肯定最后各種崩潰 。
所以通常情況下,我們會引出線程池這個概念 。
本質就是我就招了幾個固定的員工,給他們派活,某一個人的活干完了再去任務中心領取新的活 。
防止任務太多,一次性招太多工人,最后系統崩潰 。
開心一刻
理想的多線程
可能也是因為線程池這個東西用的越來越多了吧,從Python3.2+之后,就成了內置模塊 。
對的,直接就能使用,不需要pip進行安裝什么的 。
concurrent.futures下面主要有倆接口 。
ThreadPoolExecutor 線程池 。ProcessPoolExecutor進程池 。
【python循環內存溢出 python多進程進程池】這里可沒有什么所謂的異步池 。
個人看法:雖然異步的性能很高,但是目前除了Go以外,其他實現的都不是太好,用法上面有些怪異,當然,你們可以說我菜,我承認 。
線程池
示例代碼
import timefrom concurrent.futures import ThreadPoolExecutorimport random# max_workers表示工人數量,也就是線程池里面的線程數量pool = ThreadPoolExecutor(max_workers=10)# 任務列表task_list = ["任務1", "任務2", "任務3", "任務4", ]def handler(task_name):# 隨機睡眠,模仿任務執行時間不確定性n = random.randrange(5)time.sleep(n)print(f"任務內容:{task_name}")if __name__ == '__main__':# 遍歷任務,for task in task_list:"""交給函數處理,submit會將所有任務都提交到一個地方,不會阻塞然后線程池里面的每個線程會來取任務,比如:線程池有3個線程,但是有5個任務會先取走三個任務,每個線程去處理其中一個線程處理完自己的任務之后,會再來提交過的任務區再拿走一個任務"""pool.submit(handler, task)print("main執行完畢")執行結果其實這個就是并發的,不要懷疑,但是你有沒有發現個問題,main先執行,這說明啥?
這說明,我main跑完之后,是不管子線程的死活的 。
那能不能設置一下,所有的子線程都執行完之后,main函數在執行完?
當然可以,需要一個參數即可 。
pool.shutdown()要完成上述的問題,我們需要一個參數,加上這個參數之后 。就可以讓主線程等待所有子線程執行完之后,主線程再執行完 。
示例代碼
...if __name__ == '__main__':# 遍歷任務,for task in task_list:"""交給函數處理,submit會將所有任務都提交到一個地方然后線程池里面的每個線程會來取任務,比如:線程池有3個線程,但是有5個任務會先取走三個任務,每個線程去處理其中一個線程處理完自己的任務之后,會再來提交過的任務區再拿走一個任務"""pool.submit(handler, task)pool.shutdown()print("main執行完畢")主要就是13行的pool.shutdown() 。執行結果
add_done_callbackadd_done_callback可以理解為是回調函數,線程執行完之后,會自動調用指定的回調函數 。并且能拿到線程執行函數的返回值 。
有什么用,我也沒用過,怪我才疏學淺叭 。
示例代碼
import timefrom concurrent.futures import ThreadPoolExecutorimport randomfrom concurrent.futures._base import Future# max_workers表示工人數量,也就是線程池里面的線程數量pool = ThreadPoolExecutor(max_workers=10)# 任務列表task_list = ["任務1", "任務2", "任務3", "任務4", ]def handler(task_name):# 隨機睡眠,模仿任務執行時間不確定性n = random.randrange(5)time.sleep(n)print(f"任務內容:{task_name}")return f"任務內容:{task_name}"def done(res: Future):print("done拿到的返回值:", res.result())if __name__ == '__main__':# 遍歷任務,for task in task_list:futrue = pool.submit(handler, task) # type:Futurefutrue.add_done_callback(done)pool.shutdown()print("main執行完畢")注意:第17,27,28行代碼!執行效果
多進程方式
其實通過上述幾個例子,我們基本是知道怎么使用上面這個線程池了 。
但是都知道Python的線程,因為GIL(全局解釋器鎖)的原因,是不能并發到多個物理核心上的 。
所以是IO密集型的,像爬蟲,讀寫文件,使用線程池是ok的 。
但是如果說我就是野,就是頭鐵,非要用Python做計算型應用,像圖片壓縮、視頻流推送,那沒辦法,需要使用多進程池方式 。
其實通過concurrent這個接口,可以很方便的創建進程池,只需要修改兩個地方 。
...# 改成導入進程池方式from concurrent.futures import ProcessPoolExecutor...if __name__ == '__main__':...# 進程池方式pool = ProcessPoolExecutor(max_workers=10)...只需要修改這倆地方即可,其他和上述用法一摸一樣 。總結
本篇主要講的是Python自帶的線程池和進程池 。
比較有特色的是,ThreadPoolExecutor,ProcessPoolExecutor的接口是一樣的 。
只需要修改導入的包就行 。
concurrent的接口主要有pool.submit(),pool.shutdown(),futrue.add_done_callback() 。
基本這幾個都夠自己用了 。
如果在操作過程中有任何問題,記得下面留言,我們看到會第一時間解決問題 。
- win10內存占用高怎么解決 聯想win10內存占用高
- 溫度轉換python代碼怎么運行 用文本文檔寫python代碼怎么運行
- python常見的數據類型有哪幾個 python的數據類型有幾種
- python服務器端開發 python應用服務器
- 內存卡怎么重新分區 內存卡分區丟失
- 內存最小的電腦瀏覽器 哪款瀏覽器占用內存小
- java中結束循環 java結束循環的命令是
- python怎樣運行 python如何打開文件
- mac怎么看自己的內存 如何查看mac內存使用
- python和java有什么關系 JAVA和Python的區別
