自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇文章淺析Python自帶的線程池和進(jìn)程池

開發(fā) 前端
我們都知道,不管是Java,還是C++,還是Go,還是Python,都是有線程這個(gè)概念的。但是我們知道,線程是不能隨便創(chuàng)建的,就像每招一個(gè)員工一樣,是有代價(jià)的,無限制招人肯定最后各種崩潰。所以通常情況下,我們會(huì)引出線程池這個(gè)概念。

[[385920]]

前言

大家好,我是星期八。

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

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

所以通常情況下,我們會(huì)引出線程池這個(gè)概念。

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

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

開心一刻

理想的多線程

[[385921]]

 

實(shí)際的多線程

 

 


 

[[385922]]

 

from concurrent.futures import ...

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

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

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

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

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

個(gè)人看法:雖然異步的性能很高,但是目前除了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í)行時(shí)間不確定性 
  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會(huì)將所有任務(wù)都提交到一個(gè)地方,不會(huì)阻塞 
  23.             然后線程池里面的每個(gè)線程會(huì)來取任務(wù), 
  24.             比如:線程池有3個(gè)線程,但是有5個(gè)任務(wù) 
  25.             會(huì)先取走三個(gè)任務(wù),每個(gè)線程去處理 
  26.             其中一個(gè)線程處理完自己的任務(wù)之后,會(huì)再來提交過的任務(wù)區(qū)再拿走一個(gè)任務(wù) 
  27.         ""
  28.         pool.submit(handler, task) 
  29.     print("main執(zhí)行完畢"

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

 

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

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

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

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

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

  1. pool.shutdown() 

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

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

示例代碼

  1. ... 
  2. if __name__ == '__main__'
  3.     # 遍歷任務(wù), 
  4.     for task in task_list: 
  5.         ""
  6.             交給函數(shù)處理,submit會(huì)將所有任務(wù)都提交到一個(gè)地方 
  7.             然后線程池里面的每個(gè)線程會(huì)來取任務(wù), 
  8.             比如:線程池有3個(gè)線程,但是有5個(gè)任務(wù) 
  9.             會(huì)先取走三個(gè)任務(wù),每個(gè)線程去處理 
  10.             其中一個(gè)線程處理完自己的任務(wù)之后,會(huì)再來提交過的任務(wù)區(qū)再拿走一個(gè)任務(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í)行完之后,會(huì)自動(dòng)調(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í)行時(shí)間不確定性 
  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í)通過上述幾個(gè)例子,我們基本是知道怎么使用上面這個(gè)線程池了。

但是都知道Python的線程,因?yàn)镚IL(全局解釋器鎖)的原因,是不能并發(fā)到多個(gè)物理核心上的。

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

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

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

  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()。

基本這幾個(gè)都?jí)蜃约河昧恕?/p>

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

 

責(zé)任編輯:武曉燕 來源: Python爬蟲與數(shù)據(jù)挖掘
相關(guān)推薦

2021-05-15 09:18:04

Python進(jìn)程

2019-09-24 14:19:12

PythonC語(yǔ)言文章

2021-02-15 13:38:38

多線程異步模型

2021-01-14 09:04:27

Django FormForm組件開發(fā)

2020-10-09 08:15:11

JsBridge

2021-05-12 16:09:18

Python分布式進(jìn)程接口

2024-04-11 13:30:59

PythonProcess

2021-05-21 09:01:56

Python繼承多態(tài)

2017-01-10 13:39:57

Python線程池進(jìn)程池

2018-04-09 16:35:10

數(shù)據(jù)庫(kù)MySQLInnoDB

2021-05-18 09:00:28

Pythonclass

2017-09-05 08:52:37

Git程序員命令

2021-04-24 10:19:41

Python函數(shù)指向

2025-02-19 10:39:26

Python高階函數(shù)函數(shù)名

2022-02-21 09:44:45

Git開源分布式

2023-05-12 08:19:12

Netty程序框架

2021-06-30 00:20:12

Hangfire.NET平臺(tái)

2019-04-17 15:16:00

Sparkshuffle算法

2024-06-25 08:18:55

2021-04-09 08:40:51

網(wǎng)絡(luò)保險(xiǎn)網(wǎng)絡(luò)安全網(wǎng)絡(luò)風(fēng)險(xiǎn)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)