Python多進程與多線程適用場景案例分析
你想明確多進程和多線程各自的適用場景,核心是要結(jié)合任務(wù)類型、資源需求、數(shù)據(jù)共享等維度來判斷——簡單來說,IO密集型任務(wù)優(yōu)先用多線程,CPU密集型任務(wù)必須用多進程,下面拆解具體場景和選型邏輯,附實戰(zhàn)案例幫你落地。
一、多線程(threading):主打“IO密集型”場景
多線程的核心優(yōu)勢是“輕量、切換快、數(shù)據(jù)共享方便”,但受GIL限制無法利用多核,因此只適合“等待時間遠大于計算時間”的任務(wù)(IO等待時線程釋放GIL,其他線程可執(zhí)行)。
1. 核心適用場景(附案例)
(1)網(wǎng)絡(luò)相關(guān)任務(wù)(最典型)
- 爬蟲(批量爬取網(wǎng)頁、接口數(shù)據(jù))、API調(diào)用、消息隊列消費、網(wǎng)絡(luò)監(jiān)控;
- 案例:多線程爬取10個網(wǎng)頁(IO等待占90%)
import threading
import time
import requests
def crawl(url):
print(f"線程{threading.current_thread().name}:請求{url}")
resp = requests.get(url) 網(wǎng)絡(luò)IO等待(釋放GIL)
print(f"{url}:狀態(tài)碼{resp.status_code}")
if __name__ == "__main__":
start = time.time()
urls = [f"https://httpbin.org/get?num={i}" for i in range(10)]
threads = [threading.Thread(target=crawl, args=(url,)) for url in urls]
[t.start() for t in threads]
[t.join() for t in threads]
print(f"總耗時:{time.time()-start:.2f}秒") 約2秒(并發(fā)),單線程約10秒(2)文件/數(shù)據(jù)庫IO任務(wù)
- 批量讀寫本地文件、數(shù)據(jù)庫查詢/插入(如MySQL/Redis操作)、日志采集;
- 特點:這類任務(wù)大部分時間在“等磁盤/數(shù)據(jù)庫響應(yīng)”,線程切換開銷可忽略;
- 案例:多線程讀取10個大文本文件
from concurrent.futures import ThreadPoolExecutor
import os
def read_file(filepath):
with open(filepath, "r", encoding="utf-8") as f:
content = f.read()
return f"{filepath}:字符數(shù){len(content)}"
if __name__ == "__main__":
files = [f for f in os.listdir() if f.endswith(".txt")][:10]
with ThreadPoolExecutor(max_workers=5) as executor:
results = executor.map(read_file, files)
for res in results:
print(res)(3)需頻繁數(shù)據(jù)共享的輕量任務(wù)
- 實時統(tǒng)計(如統(tǒng)計程序運行狀態(tài)、實時計數(shù))、GUI程序后臺任務(wù)(如界面刷新+數(shù)據(jù)加載);
- 特點:線程共享進程內(nèi)存,無需復(fù)雜通信,加鎖即可保證數(shù)據(jù)安全;
- 案例:多線程實時計數(shù)(共享變量)
import threading
import time
count = 0
lock = threading.Lock()
def add_count():
global count
for _ in range(10000):
with lock: 加鎖避免數(shù)據(jù)競爭
count += 1
if __name__ == "__main__":
t1 = threading.Thread(target=add_count)
t2 = threading.Thread(target=add_count)
t1.start()
t2.start()
t1.join()
t2.join()
print(f"最終計數(shù):{count}") 輸出20000(準確)2. 多線程避坑場景
- ? 絕對不要用多線程處理CPU密集任務(wù)(如矩陣運算、數(shù)據(jù)加密):GIL會讓多線程變成“偽并發(fā)”,效率甚至低于單線程;
- ? 不要創(chuàng)建過多線程(如上千個):線程切換開銷累積,會導(dǎo)致程序卡頓。
二、多進程(multiprocessing):主打“CPU密集型”場景
多進程的核心優(yōu)勢是“突破GIL限制、利用多核CPU、進程隔離更穩(wěn)定”,但啟動/通信開銷大,適合“計算時間占主導(dǎo)”的任務(wù)。
1. 核心適用場景(附案例)
(1)數(shù)據(jù)計算類任務(wù)(最典型)
- 矩陣運算、數(shù)值模擬、數(shù)據(jù)挖掘(如批量特征計算)、密碼破解、AI模型訓(xùn)練(單機多進程);
- 案例:多進程計算10個大矩陣的乘法
from concurrent.futures import ProcessPoolExecutor
import time
import numpy as np
def matrix_calc(matrix):
return np.dot(matrix, matrix) 純CPU計算
if __name__ == "__main__":
start = time.time()
matrices = [np.random.rand(1000, 1000) for _ in range(10)]
with ProcessPoolExecutor() as executor:
executor.map(matrix_calc, matrices)
print(f"總耗時:{time.time()-start:.2f}秒") 4核CPU約3秒,單進程約10秒(2)批量獨立任務(wù)處理
- 圖片/視頻處理(如批量壓縮圖片、視頻轉(zhuǎn)碼)、文件格式轉(zhuǎn)換(如CSV轉(zhuǎn)Excel)、批量數(shù)據(jù)分析;
- 特點:任務(wù)間無依賴、可獨立執(zhí)行,進程隔離避免一個任務(wù)崩潰影響全局;
- 案例:多進程批量壓縮圖片
import multiprocessing
from PIL import Image
import os
def compress_img(filepath):
img = Image.open(filepath)
img.save(f"compressed_{filepath}", quality=50) 壓縮圖片(CPU密集)
return f"{filepath}壓縮完成"
if __name__ == "__main__":
imgs = [f for f in os.listdir() if f.endswith((".jpg", ".png"))][:5]
pool = multiprocessing.Pool(processes=4)
results = pool.map(compress_img, imgs)
pool.close()
pool.join()
for res in results:
print(res)(3)高穩(wěn)定性要求的任務(wù)
- 批量執(zhí)行第三方腳本/工具、不穩(wěn)定的任務(wù)(如調(diào)用易崩潰的接口);
- 特點:單個進程崩潰不會導(dǎo)致整個程序掛掉,容錯性更高。
2. 多進程避坑場景
- ? 不要用多進程處理高頻小任務(wù)(如每秒執(zhí)行一次的定時檢測):進程啟動/通信開銷會抵消并行優(yōu)勢;
- ? 不要用多進程處理需頻繁數(shù)據(jù)共享的任務(wù):進程間通信(Queue/Pipe)開銷大,效率遠低于線程。
三、選型速查表(新手直接套用)
| 任務(wù)特征 | 優(yōu)先選擇 | 核心原因 |
|---|---|---|
| CPU密集(計算為主) | 多進程 | 突破GIL,利用多核并行計算 |
| IO密集(等待為主) | 多線程 | 輕量并發(fā),IO等待時釋放GIL |
| 需頻繁共享數(shù)據(jù) | 多線程 | 共享內(nèi)存,通信成本低 |
| 任務(wù)獨立、無數(shù)據(jù)共享 | 多進程 | 進程隔離,穩(wěn)定性高 |
| 任務(wù)數(shù)量多、啟動頻繁 | 多線程 | 線程啟動快,切換開銷低 |
| 單個任務(wù)易崩潰 | 多進程 | 進程隔離,不影響其他任務(wù) |
| 單機最大化算力 | 多進程 | 充分利用多核CPU |
四、特殊場景:混合使用(線程+進程)
如果任務(wù)是“IO+CPU混合”(如爬取數(shù)據(jù)后立即計算),可結(jié)合二者優(yōu)勢:
示例:多進程(處理CPU計算)+ 多線程(處理IO爬取)
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import requests
import numpy as np
線程:爬取數(shù)據(jù)(IO)
def crawl_data(url):
resp = requests.get(url)
return resp.json()["data"]
進程:處理數(shù)據(jù)(CPU)
def process_data(data_list):
arr = np.array(data_list)
return arr.mean() 數(shù)值計算
if __name__ == "__main__":
1. 多線程爬取數(shù)據(jù)
urls = [f"https://httpbin.org/get?data={i}" for i in range(10)]
with ThreadPoolExecutor(max_workers=5) as t_executor:
data = list(t_executor.map(crawl_data, urls))
2. 多進程處理數(shù)據(jù)
with ProcessPoolExecutor() as p_executor:
result = p_executor.submit(process_data, data).result()
print(f"數(shù)據(jù)均值:{result}")到此這篇關(guān)于Python多進程與多線程適用場景案例分析的文章就介紹到這了,更多相關(guān)Python多進程與多線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python3.5 + sklearn利用SVM自動識別字母驗證碼方法示例
這篇文章主要給大家介紹了關(guān)于Python3.5 + sklearn利用SVM自動識別字母驗證碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
基于Python+Matplotlib繪制漸變色扇形圖與等高線圖
這篇文章主要為大家介紹了如何利用Python中的Matplotlib繪制漸變色扇形圖與等高線圖,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下方法2022-04-04
使用Python對接OpenAi?API實現(xiàn)智能QQ機器人的方法
這篇文章主要介紹了使用Python對接OpenAi?API實現(xiàn)智能QQ機器人的方法,主要是提供一個方法思路,可以根據(jù)實現(xiàn)代碼延申出更多的解決方法,需要的朋友可以參考下2023-03-03
聽歌識曲--用python實現(xiàn)一個音樂檢索器的功能
本篇文章中主要介紹了用python實現(xiàn)一個音樂檢索器,類似于QQ音樂的搖一搖識曲,有興趣的同學(xué)可以了解一下。2016-11-11
python實現(xiàn)幾種歸一化方法(Normalization Method)
這篇文章主要介紹了python實現(xiàn)幾種歸一化方法(Normalization Method),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07

