一、理解多線程的適用場景 I/O 密集型任務 當程序主要是在等待外部輸入 / 輸出(I/O)操作完成時,如讀取文件、*請求等,多線程可以顯著提高效率。例如,在一個*爬蟲程序中,需要從多個網(wǎng)頁獲取數(shù)據(jù)。如果使用單線程,程序會依次請求每個網(wǎng)頁,等待一個網(wǎng)頁的數(shù)據(jù)完全返回后再請求下一個。但如果使用多線程,可以同時發(fā)起多個網(wǎng)頁請求,當一個線程在等待某個網(wǎng)頁的響應時,其他線程可以繼續(xù)處理其他網(wǎng)頁的請求。 示例代碼: 收起
import requests import threading def download_page(url): resp*e = requests.get(url) print(f"Downloaded {url}, status code: {resp*e.status_code}") urls = ["https://www.example1.com", "https://www.example2.com", "https://www.example3.com"] threads = [] for url in urls: thread = threading.Thread(target=download_page, args=(url,)) thread.start() threads.append(thread) for thread in threads: thread.join()
在這個例子中,我們創(chuàng)建了多個線程來并發(fā)地下載網(wǎng)頁內(nèi)容。每個線程負責下載一個指定的網(wǎng)頁,這樣可以大大加快整個下載過程。 不適合 CPU 密集型任務(在 CPython 解釋器下) 由于 Python 的全局解釋器鎖(GIL)的存在,在 CPython(最常用的 Python 解釋器)中,多線程在處理 CPU 密集型任務(如復雜的數(shù)學計算)時,并不能充分利用多核 CPU 的優(yōu)勢。因為同一時間只有一個線程可以執(zhí)行 Python 字節(jié)碼。例如,一個計算斐波那契數(shù)列的函數(shù),在多線程環(huán)境下運行多個這樣的計算任務,并不會比單線程快很多,因為多個線程會競爭 GIL,大部分時間都在等待獲取 GIL 來執(zhí)行代碼。 不過,如果是在一些不帶有 GIL 的 Python 解釋器(如 Jython 或 IronPython)下,多線程對于 CPU 密集型任務可以更好地利用多核 CPU。
二、線程的創(chuàng)建和啟動 使用threading模塊創(chuàng)建線程 可以通過定義一個函數(shù)作為線程要執(zhí)行的任務,然后使用threading.Thread類來創(chuàng)建線程對象。線程對象的target參數(shù)指定要執(zhí)行的函數(shù),args參數(shù)(可選)指定傳遞給函數(shù)的參數(shù)。 示例:
import threading
def print_numbers():
for i in range(10):
print(i)
thread = threading.Thread(target=print_numbers)
thread.start()