日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
一篇文章淺析Python自帶的線程池和進(jìn)程池

前言

成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都做網(wǎng)站、網(wǎng)站建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、湖州網(wǎng)絡(luò)推廣、微信平臺小程序開發(fā)、湖州網(wǎng)絡(luò)營銷、湖州企業(yè)策劃、湖州品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供湖州建站搭建服務(wù),24小時服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com

大家好,我是星期八。

我們都知道,不管是Java,還是C++,還是Go,還是Python,都是有線程這個概念的。

但是我們知道,線程是不能隨便創(chuàng)建的,就像每招一個員工一樣,是有代價的,無限制招人肯定最后各種崩潰。

所以通常情況下,我們會引出線程池這個概念。

本質(zhì)就是我就招了幾個固定的員工,給他們派活,某一個人的活干完了再去任務(wù)中心領(lǐng)取新的活。

防止任務(wù)太多,一次性招太多工人,最后系統(tǒng)崩潰。

開心一刻

理想的多線程

實(shí)際的多線程

from concurrent.futures import ...

可能也是因為線程池這個東西用的越來越多了吧,從Python3.2+之后,就成了內(nèi)置模塊。

對的,直接就能使用,不需要pip進(jìn)行安裝什么的。

concurrent.futures下面主要有倆接口。

  • ThreadPoolExecutor 線程池。
  • ProcessPoolExecutor進(jìn)程池。

這里可沒有什么所謂的異步池。

個人看法:雖然異步的性能很高,但是目前除了Go以外,其他實(shí)現(xiàn)的都不是太好,用法上面有些怪異,當(dāng)然,你們可以說我菜,我承認(rèn)。

線程池

示例代碼

 
 
 
 
  1. import time 
  2. from concurrent.futures import ThreadPoolExecutor 
  3. import random 
  4.  
  5. # max_workers表示工人數(shù)量,也就是線程池里面的線程數(shù)量 
  6. pool = ThreadPoolExecutor(max_workers=10) 
  7. # 任務(wù)列表 
  8. task_list = ["任務(wù)1", "任務(wù)2", "任務(wù)3", "任務(wù)4", ] 
  9.  
  10.  
  11. def handler(task_name): 
  12.     # 隨機(jī)睡眠,模仿任務(wù)執(zhí)行時間不確定性 
  13.     n = random.randrange(5) 
  14.     time.sleep(n) 
  15.     print(f"任務(wù)內(nèi)容:{task_name}") 
  16.  
  17.  
  18. if __name__ == '__main__': 
  19.     # 遍歷任務(wù), 
  20.     for task in task_list: 
  21.         """ 
  22.             交給函數(shù)處理,submit會將所有任務(wù)都提交到一個地方,不會阻塞 
  23.             然后線程池里面的每個線程會來取任務(wù), 
  24.             比如:線程池有3個線程,但是有5個任務(wù) 
  25.             會先取走三個任務(wù),每個線程去處理 
  26.             其中一個線程處理完自己的任務(wù)之后,會再來提交過的任務(wù)區(qū)再拿走一個任務(wù) 
  27.         """ 
  28.         pool.submit(handler, task) 
  29.     print("main執(zhí)行完畢") 

執(zhí)行結(jié)果

 

發(fā)現(xiàn)的問題

其實(shí)這個就是并發(fā)的,不要懷疑,但是你有沒有發(fā)現(xiàn)個問題,main先執(zhí)行,這說明啥?

這說明,我main跑完之后,是不管子線程的死活的。

那能不能設(shè)置一下,所有的子線程都執(zhí)行完之后,main函數(shù)在執(zhí)行完?

當(dāng)然可以,需要一個參數(shù)即可。

 
 
 
 
  1. pool.shutdown() 

要完成上述的問題,我們需要一個參數(shù),加上這個參數(shù)之后。

就可以讓主線程等待所有子線程執(zhí)行完之后,主線程再執(zhí)行完。

示例代碼

 
 
 
 
  1. ... 
  2. if __name__ == '__main__': 
  3.     # 遍歷任務(wù), 
  4.     for task in task_list: 
  5.         """ 
  6.             交給函數(shù)處理,submit會將所有任務(wù)都提交到一個地方 
  7.             然后線程池里面的每個線程會來取任務(wù), 
  8.             比如:線程池有3個線程,但是有5個任務(wù) 
  9.             會先取走三個任務(wù),每個線程去處理 
  10.             其中一個線程處理完自己的任務(wù)之后,會再來提交過的任務(wù)區(qū)再拿走一個任務(wù) 
  11.         """ 
  12.         pool.submit(handler, task) 
  13.     pool.shutdown() 
  14.     print("main執(zhí)行完畢") 

主要就是13行的pool.shutdown()。

執(zhí)行結(jié)果

 

這次結(jié)果就是我們想要的了,hhh!!!

 
 
 
 
  1. add_done_callback 

add_done_callback可以理解為是回調(diào)函數(shù),線程執(zhí)行完之后,會自動調(diào)用指定的回調(diào)函數(shù)。

并且能拿到線程執(zhí)行函數(shù)的返回值。

有什么用,我也沒用過,怪我才疏學(xué)淺叭。

示例代碼

 
 
 
 
  1. import time 
  2. from concurrent.futures import ThreadPoolExecutor 
  3. import random 
  4. from concurrent.futures._base import Future 
  5.  
  6. # max_workers表示工人數(shù)量,也就是線程池里面的線程數(shù)量 
  7. pool = ThreadPoolExecutor(max_workers=10) 
  8. # 任務(wù)列表 
  9. task_list = ["任務(wù)1", "任務(wù)2", "任務(wù)3", "任務(wù)4", ] 
  10.  
  11.  
  12. def handler(task_name): 
  13.     # 隨機(jī)睡眠,模仿任務(wù)執(zhí)行時間不確定性 
  14.     n = random.randrange(5) 
  15.     time.sleep(n) 
  16.     print(f"任務(wù)內(nèi)容:{task_name}") 
  17.     return f"任務(wù)內(nèi)容:{task_name}" 
  18.  
  19.  
  20. def done(res: Future): 
  21.     print("done拿到的返回值:", res.result()) 
  22.  
  23.  
  24. if __name__ == '__main__': 
  25.     # 遍歷任務(wù), 
  26.     for task in task_list: 
  27.         futrue = pool.submit(handler, task)  # type:Future 
  28.         futrue.add_done_callback(done) 
  29.     pool.shutdown() 
  30.     print("main執(zhí)行完畢") 

注意:第17,27,28行代碼!

執(zhí)行效果

 

我想,可能通常用在一些善后工作叭。

多進(jìn)程方式

其實(shí)通過上述幾個例子,我們基本是知道怎么使用上面這個線程池了。

但是都知道Python的線程,因為GIL(全局解釋器鎖)的原因,是不能并發(fā)到多個物理核心上的。

所以是IO密集型的,像爬蟲,讀寫文件,使用線程池是ok的。

但是如果說我就是野,就是頭鐵,非要用Python做計算型應(yīng)用,像圖片壓縮、視頻流推送,那沒辦法,需要使用多進(jìn)程池方式。

其實(shí)通過concurrent這個接口,可以很方便的創(chuàng)建進(jìn)程池,只需要修改兩個地方。

 
 
 
 
  1. ... 
  2. # 改成導(dǎo)入進(jìn)程池方式 
  3. from concurrent.futures import ProcessPoolExecutor 
  4. ... 
  5. if __name__ == '__main__': 
  6.     ... 
  7.     # 進(jìn)程池方式 
  8.     pool = ProcessPoolExecutor(max_workers=10) 
  9.     ... 

只需要修改這倆地方即可,其他和上述用法一摸一樣。

總結(jié)

本篇主要講的是Python自帶的線程池和進(jìn)程池。

比較有特色的是,ThreadPoolExecutor,ProcessPoolExecutor的接口是一樣的。

只需要修改導(dǎo)入的包就行。

concurrent的接口主要有pool.submit(),pool.shutdown(),futrue.add_done_callback()。

基本這幾個都夠自己用了。

本文轉(zhuǎn)載自微信公眾號「 Python爬蟲與數(shù)據(jù)挖掘」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系 Python爬蟲與數(shù)據(jù)挖掘公眾號。


本文名稱:一篇文章淺析Python自帶的線程池和進(jìn)程池
當(dāng)前路徑:http://www.dlmjj.cn/article/dhpchge.html