1. 前言
Python 是一種因其簡潔與彈性而廣受開發者喜愛的程式語言。其中,使用執行緒(Thread)是實現高效程式設計的重要技術之一。本文將從基礎到進階應用,深入淺出地介紹 Python 中的執行緒運用方式。
什麼是執行緒?
執行緒是在程式中可以獨立運行的小單位。在同一個行程(Process)中可以有多個執行緒同時運作,實現任務的並行處理。這種設計能提升程式執行效率,並善用系統資源。
為什麼要在 Python 中學習執行緒?
透過執行緒,我們可以有效解決以下幾種常見情境:
- 提升 I/O 操作效率
對於包含大量檔案存取或網路通訊的任務,使用執行緒可以縮短等待時間。 - 同時處理多個任務
例如同時處理大量資料或並行發送多個 API 請求等。 - 提升使用者體驗
在 GUI 應用中,可將重度運算放在背景執行,保持操作介面的即時反應。
本文將學到的內容
本文將涵蓋以下與 Python 執行緒相關的主題:
- 執行緒的基本概念與使用方式
- 避免執行緒之間資料衝突的方法
- GIL(全域直譯器鎖)的原理與影響
- 在實際應用中如何善用執行緒
- 最佳實踐與注意事項
從新手也能理解的基礎說明,到實務應用範例皆有涵蓋,是想深入了解 Python 執行緒的理想指南。
2. 執行緒的基本概念
執行緒是實現程式並行處理的基本機制。本節將說明執行緒的基本運作原理,並介紹其與行程的差異。
什麼是執行緒?
執行緒是程式中可以獨立執行的運算單位。一般來說,一個程式作為行程運作,而行程中可以包含一個或多個執行緒。
舉例來說,瀏覽器中可能同時執行以下幾個執行緒:
- 監控使用者輸入
- 網頁內容渲染
- 影音串流播放
透過執行緒,這些任務能夠同時高效執行。
行程與執行緒的差異
要理解執行緒的運作,需先掌握其與行程的主要差異。
項目 | 行程(Process) | 執行緒(Thread) |
---|---|---|
記憶體空間 | 彼此獨立 | 共享同一行程內的記憶體 |
建立成本 | 高(每個行程需個別配置記憶體) | 低(因共用記憶體而更有效率) |
溝通方式 | 需使用行程間通訊(IPC) | 可直接共享資料 |
並行處理的粒度 | 粗 | 細 |
在 Python 中,使用執行緒可以在共用資源的情況下進行有效率的並行處理。
並行處理與並列處理的差異
在學習執行緒的過程中,理解「並行處理(concurrent)」與「並列處理(parallel)」這兩個概念非常重要。
- 並行處理:
將多個任務輪流快速執行,讓它們看起來像是同時進行。在 Python 中的執行緒特別適合用於並行處理。
例子:一位店員輪流為多位顧客服務。 - 並列處理:
多個任務真正同時執行,通常需多核心 CPU 支援。在 Python 中,這通常透過多行程(multiprocessing)實現。
例子:多位店員同時為不同顧客服務。
Python 的執行緒主要適用於 I/O 密集型任務,例如檔案操作或網路請求。
Python 中執行緒的特性
Python 提供標準模組 threading
,讓開發者能方便地建立與管理執行緒。
但 Python 的執行緒有幾個重要的特性與限制:
- 全域直譯器鎖(GIL)
GIL 的存在使得 Python 直譯器在同一時間只能執行一個執行緒,因此對於需要大量 CPU 計算的任務,使用執行緒時效果有限。 - 適合 I/O 密集型任務
執行緒特別適合處理網路請求、檔案 I/O 等等待時間多的操作,可有效提升效能。
實際的執行緒使用範例
以下是幾個常見的執行緒使用情境:
- 網頁爬蟲(Web Scraping):
可同時擷取多個網頁資料,加快整體抓取速度。 - 資料庫存取:
可同時處理多個用戶的請求,提高回應效率。 - 背景任務處理:
當主執行緒處理使用者操作時,可在背景進行複雜或耗時的處理。
3. 在 Python 中建立執行緒
在 Python 中,可以使用 threading
模組輕鬆建立執行緒並實現並行處理。本節將說明建立與操作執行緒的基本方法。
threading 模組簡介
threading
是 Python 的標準模組,用來建立與管理執行緒。透過這個模組,你可以進行以下操作:
- 建立與啟動執行緒
- 執行緒之間的同步控制
- 追蹤與管理執行緒狀態
這個模組將執行緒視為物件,因此操作上相當直覺與彈性。
建立基本執行緒的方法
最常見的方式是使用 Thread
類別來建立執行緒。以下是基本範例:
import threading
import time
# 執行緒中執行的函式
def print_numbers():
for i in range(5):
print(f"Number: {i}")
time.sleep(1)
# 建立執行緒
thread = threading.Thread(target=print_numbers)
# 啟動執行緒
thread.start()
# 主執行緒繼續執行
print("Main thread is running...")
# 等待執行緒結束
thread.join()
print("Thread has completed.")
重點說明
- 建立執行緒:
使用threading.Thread
類別,並透過target
參數指定要在執行緒中執行的函式。 - 啟動執行緒:
呼叫start()
方法即可啟動執行緒。 - 等待執行緒完成:
使用join()
方法讓主執行緒等候直到子執行緒執行結束。
在這段程式中,print_numbers
函式會在新的執行緒中執行,而主執行緒則同時進行其他任務。
向執行緒傳遞參數
如果需要將參數傳遞給執行緒,可以使用 args
參數。以下是範例:
def print_numbers_with_delay(delay):
for i in range(5):
print(f"Number: {i}")
time.sleep(delay)
# 傳遞參數建立執行緒
thread = threading.Thread(target=print_numbers_with_delay, args=(2,))
thread.start()
thread.join()
重點說明
- 使用
args=(2,)
的方式傳遞參數,格式為元組(tuple)。 - 在上例中,傳入的
delay
為 2 秒,因此每次迴圈間會有 2 秒的延遲。
使用類別建立執行緒
若需更進階的執行緒控制,可以繼承 Thread
類別並自訂一個執行緒類別:
class CustomThread(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
for i in range(5):
print(f"{self.name} is running: {i}")
time.sleep(1)
# 建立執行緒實例
thread1 = CustomThread(name="Thread 1")
thread2 = CustomThread(name="Thread 2")
# 啟動執行緒
thread1.start()
thread2.start()
# 等待執行緒完成
thread1.join()
thread2.join()
print("All threads have completed.")
重點說明
run
方法:
覆寫Thread
類別的run()
方法,在其中定義執行緒的處理邏輯。- 命名執行緒:
透過名稱方便辨識執行緒,有助於除錯與記錄。
執行緒的狀態管理
在管理執行緒狀態時,以下方法非常有用:
is_alive()
: 檢查執行緒是否仍在執行中。setDaemon(True)
: 將執行緒設為背景(daemon)執行緒。
背景執行緒(Daemon Thread)範例
def background_task():
while True:
print("Background task is running...")
time.sleep(2)
# 建立背景執行緒
thread = threading.Thread(target=background_task)
thread.setDaemon(True) # 設定為背景模式
thread.start()
print("Main thread is exiting.")
# 背景執行緒會在主執行緒結束時自動終止
背景執行緒(Daemon Thread)會隨著主執行緒的結束而自動終止。這個特性非常適合處理後台任務,例如定時檢查或背景監控等。
4. 執行緒間的資料同步
當 Python 中的多個執行緒同時存取相同資源時,可能會發生「資料競爭(Race Condition)」的問題。本節將說明如何透過同步機制來避免這些問題。
什麼是資料競爭?
資料競爭發生於多個執行緒同時讀寫同一個變數或資源時,可能導致非預期的結果或錯誤行為。
資料競爭的範例
import threading
counter = 0
def increment():
global counter
for _ in range(1000000):
counter += 1
# 建立兩個執行緒
thread1 = threading.Thread(target=increment)
thread2 = threading.Thread(target=increment)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(f"Counter value: {counter}")
上例中,兩個執行緒同時修改 counter
變數,因為缺乏同步控制,最終結果可能不正確,並不一定會是預期的 2000000。
使用 Lock 進行同步
為了避免資料競爭,可以使用 threading
模組中的 Lock
物件,實現執行緒之間的同步。
基本的 Lock 用法
import threading
counter = 0
lock = threading.Lock()
def increment_with_lock():
global counter
for _ in range(1000000):
# 取得鎖定後執行操作
with lock:
counter += 1
# 建立兩個執行緒
thread1 = threading.Thread(target=increment_with_lock)
thread2 = threading.Thread(target=increment_with_lock)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(f"Counter value with lock: {counter}")
重點說明
with lock
語法: 使用with
可自動取得與釋放鎖定,簡潔又安全。- 鎖定期間排他控制: 當一個執行緒持有鎖時,其他執行緒會被阻塞直到鎖被釋放。
使用 Lock
後,即可確保 counter
的最終值是預期的 2000000。
遞迴鎖(RLock)
Lock
是基本的鎖機制,但如果同一個執行緒需要多次取得鎖,就必須使用 RLock
(遞迴鎖)。
RLock 範例
import threading
lock = threading.RLock()
def nested_function():
with lock:
print("第一次取得鎖")
with lock:
print("第二次取得鎖")
thread = threading.Thread(target=nested_function)
thread.start()
thread.join()
重點說明
RLock
允許同一執行緒重複取得鎖,不會造成死鎖。- 特別適合需要巢狀鎖定邏輯的情況。
使用 Semaphore 進行同步
threading.Semaphore
可用來限制同時存取某個資源的執行緒數量,非常適合控制連線數或同時執行數的情境。
Semaphore 範例
import threading
import time
semaphore = threading.Semaphore(2)
def access_resource(name):
with semaphore:
print(f"{name} 正在存取資源")
time.sleep(2)
print(f"{name} 已釋放資源")
threads = []
for i in range(5):
thread = threading.Thread(target=access_resource, args=(f"Thread-{i}",))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
重點說明
- Semaphore 可控制最多同時有幾個執行緒存取資源。
- 在上述範例中,最多允許兩個執行緒同時執行
access_resource
。
使用 Event 進行同步
threading.Event
可用於在執行緒之間傳遞「是否可執行」的訊號。這種同步機制常用於控制流程等待與觸發。
Event 範例
import threading
import time
event = threading.Event()
def wait_for_event():
print("執行緒正在等待事件觸發...")
event.wait()
print("事件已觸發,開始執行任務。")
def set_event():
time.sleep(2)
print("設定事件(event.set())")
event.set()
thread1 = threading.Thread(target=wait_for_event)
thread2 = threading.Thread(target=set_event)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
重點說明
wait()
:讓執行緒進入等待狀態,直到事件被設定。set()
:將事件設為觸發狀態,使所有等待中的執行緒繼續執行。
小結
為了避免執行緒之間的資料競爭,選擇合適的同步機制非常重要。以下是各種情境下的建議:
- 單純的同步控制:使用
Lock
- 需要重複鎖定(巢狀鎖)時:使用
RLock
- 限制同時存取資源的執行緒數量:使用
Semaphore
- 在執行緒之間傳遞執行訊號:使用
Event
5. GIL 與執行緒的限制
在使用 Python 的執行緒時,無法忽視的一個重要因素就是 GIL(全域直譯器鎖)。了解 GIL 的運作方式,才能正確評估使用執行緒的優缺點與限制。
什麼是 GIL?
GIL(Global Interpreter Lock)是 Python 直譯器(特別是 CPython)的一種內部鎖機制。它的作用是:在任一時刻,只允許一個執行緒執行 Python 的位元碼。
GIL 的設計目的
- 確保記憶體管理的安全性
- 維護 Python 物件(尤其是引用計數)的正確性與一致性
然而,這也導致 Python 的多執行緒在 CPU 密集型任務中,無法真正同時執行。
GIL 的運作範例
以下範例展示了兩個執行緒同時執行大量計算,但效果卻不像預期般加速:
import threading
import time
def cpu_bound_task():
start = time.time()
count = 0
for _ in range(10**7):
count += 1
print(f"任務完成時間: {time.time() - start:.2f} 秒")
# 建立兩個執行緒
thread1 = threading.Thread(target=cpu_bound_task)
thread2 = threading.Thread(target=cpu_bound_task)
start_time = time.time()
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(f"總耗時: {time.time() - start_time:.2f} 秒")
結果分析
即使使用了兩個執行緒,實際總耗時幾乎等同於單執行緒的兩倍。這是因為 GIL 限制了真正的同時執行。
GIL 影響較大的情境
- CPU 密集型任務
像是數值計算、影像處理等需要大量 CPU 資源的任務,在 Python 中會受到 GIL 的嚴重限制,多執行緒無法有效加速。 - I/O 密集型任務
如檔案存取、網路請求等,這類任務多為等待操作,執行緒會主動釋放 GIL,因此執行緒在這種情境下依然有效。
如何克服 GIL 的限制
1. 使用多行程(multiprocessing)
要完全避開 GIL 的影響,可以使用 multiprocessing
模組。這個模組允許你建立多個獨立的行程(每個行程擁有自己的記憶體與 GIL)。
from multiprocessing import Process
import time
def cpu_bound_task():
start = time.time()
count = 0
for _ in range(10**7):
count += 1
print(f"任務完成時間: {time.time() - start:.2f} 秒")
# 建立兩個行程
process1 = Process(target=cpu_bound_task)
process2 = Process(target=cpu_bound_task)
start_time = time.time()
process1.start()
process2.start()
process1.join()
process2.join()
print(f"總耗時: {time.time() - start_time:.2f} 秒")
重點說明
- 每個行程有獨立的記憶體與直譯器執行環境,不受 GIL 限制。
- 在進行大量 CPU 運算時,使用行程比執行緒更有效率。
2. 使用 C 擴充模組
某些 Python 的 C 擴充模組(例如 NumPy 或 Pandas)在進行內部計算時會釋放 GIL,使得可以在多執行緒環境下真正達到平行運算,提升效能。
範例:
- 使用 NumPy 進行大量數值計算。
- 透過 Cython 或 Numba 將 Python 程式編譯為機器碼,加速執行。
3. 善用 asyncio 進行非同步處理
對於 I/O 密集型任務,與其使用執行緒,不如使用 asyncio
模組實現非同步處理。這可在單一執行緒中有效進行多任務切換。
範例:
import asyncio
async def io_bound_task(name, delay):
print(f"{name} 開始執行")
await asyncio.sleep(delay)
print(f"{name} 執行完畢")
async def main():
await asyncio.gather(
io_bound_task("任務 1", 2),
io_bound_task("任務 2", 3)
)
asyncio.run(main())
重點說明
- asyncio 屬於非同步架構,與多執行緒不同,不會受到 GIL 限制。
- 特別適合處理網路請求、檔案操作等大量等待的 I/O 任務。
GIL 的優點與缺點
優點
- 簡化 Python 的記憶體管理。
- 提升單一執行緒環境下的資料安全性。
缺點
- 限制了多執行緒在 CPU 密集型任務中的效能。
- 若需真正的平行處理,需轉向使用多行程。
小結
GIL 是 Python 中影響多執行緒效能的重要機制,但只要理解其原理與限制,就能選擇合適的策略來因應:
- CPU 密集型任務:建議使用
multiprocessing
模組或 C 擴充模組(如 NumPy、Cython)。 - I/O 密集型任務:可使用
threading
或asyncio
進行有效處理。
6. 實作範例:使用執行緒的實用程式
如果善加利用,執行緒可以有效處理各種複雜任務。本節將介紹幾個實際應用 Python 執行緒的範例。
1. 並行抓取多個網頁
在進行網頁爬蟲時,若需從多個網站同時擷取資料,使用執行緒可大幅縮短總耗時。
import threading
import requests
def fetch_url(url):
response = requests.get(url)
print(f"已抓取 {url}:{len(response.content)} bytes")
urls = [
"https://example.com",
"https://httpbin.org",
"https://www.python.org",
]
threads = []
# 為每個 URL 建立執行緒
for url in urls:
thread = threading.Thread(target=fetch_url, args=(url,))
threads.append(thread)
thread.start()
# 等待所有執行緒完成
for thread in threads:
thread.join()
print("所有網頁皆已抓取完畢。")
重點說明
- 透過執行緒同時發送多個請求,大幅提升資料抓取效率。
- 使用
requests
模組簡單又方便地執行 HTTP 請求。
2. 同時讀寫多個檔案
使用執行緒可讓我們同時處理大量檔案的讀寫作業,有效提升處理速度。
import threading
def write_to_file(filename, content):
with open(filename, 'w') as f:
f.write(content)
print(f"已寫入 {filename}")
files = [
("file1.txt", "Content for file 1"),
("file2.txt", "Content for file 2"),
("file3.txt", "Content for file 3"),
]
threads = []
# 為每個檔案建立一個執行緒
for filename, content in files:
thread = threading.Thread(target=write_to_file, args=(filename, content))
threads.append(thread)
thread.start()
# 等待所有執行緒完成
for thread in threads:
thread.join()
print("所有檔案皆已寫入完畢。")
重點說明
- 每個執行緒負責處理一個檔案的寫入,並行處理能大幅節省時間。
- 當不同執行緒存取的是彼此獨立的資源(例如不同檔案),使用執行緒是非常有效的方式。
3. GUI 應用中的背景處理
在圖形介面(GUI)應用中,主執行緒通常負責處理使用者互動。若將耗時任務放在主執行緒中,會導致介面卡頓或無法回應。此時可使用執行緒將重度運算放到背景執行。
以下是使用 tkinter
的簡單範例:
import threading
import time
from tkinter import Tk, Button, Label
def long_task(label):
label.config(text="任務執行中...")
time.sleep(5) # 模擬耗時處理
label.config(text="任務已完成!")
def start_task(label):
thread = threading.Thread(target=long_task, args=(label,))
thread.start()
# 建立 GUI
root = Tk()
root.title("多執行緒 GUI 範例")
label = Label(root, text="點擊按鈕開始任務。")
label.pack(pady=10)
button = Button(root, text="開始任務", command=lambda: start_task(label))
button.pack(pady=10)
root.mainloop()
重點說明
- 使用執行緒執行耗時任務,可避免主視窗(UI)被卡住。
- 透過
threading.Thread
,任務能在背景中非同步執行。
4. 即時資料處理
在處理感測器數據或日誌紀錄等即時資料時,可透過多個執行緒同時進行處理,以提升效率。
import threading
import time
import random
def process_data(sensor_name):
for _ in range(5):
data = random.randint(0, 100)
print(f"{sensor_name} 讀取資料:{data}")
time.sleep(1)
sensors = ["Sensor-1", "Sensor-2", "Sensor-3"]
threads = []
# 為每個感測器建立一個執行緒
for sensor in sensors:
thread = threading.Thread(target=process_data, args=(sensor,))
threads.append(thread)
thread.start()
# 等待所有執行緒完成
for thread in threads:
thread.join()
print("所有感測器資料皆已處理完畢。")
重點說明
- 每個感測器由一個獨立執行緒處理其資料,實現真正的並行處理。
- 此模式適合即時資料收集、即時監控或串流資料分析等應用場景。
小結
透過這些實際範例,我們學會了如何運用 Python 執行緒來設計高效的應用程式。
- 網頁爬蟲:使用執行緒並行抓取多個網頁,加快資料擷取速度。
- 檔案操作:同時處理多個檔案的讀寫作業,提升效能。
- GUI 應用:將耗時任務放到背景執行,避免畫面卡頓。
- 即時資料處理:並行處理多個感測器資料或串流訊息,實現即時性。
執行緒是一項強大工具,但在使用時必須設計得當,特別要注意資料競爭與死結(deadlock)等問題。
7. 使用執行緒時的最佳實踐
執行緒能有效提升並行處理能力,但若使用不當,可能會導致死結(Deadlock)或資料競爭等問題。本節將介紹在 Python 中使用執行緒時應遵循的重要原則與技巧。
1. 避免死結(Deadlock)
死結是指多個執行緒互相等待彼此釋放鎖,造成程式無限卡住的狀況。避免方法包括統一鎖定順序與設置超時。
死結範例
import threading
import time
lock1 = threading.Lock()
lock2 = threading.Lock()
def thread1_task():
with lock1:
print("Thread 1 已取得 lock1")
time.sleep(1)
with lock2:
print("Thread 1 已取得 lock2")
def thread2_task():
with lock2:
print("Thread 2 已取得 lock2")
time.sleep(1)
with lock1:
print("Thread 2 已取得 lock1")
thread1 = threading.Thread(target=thread1_task)
thread2 = threading.Thread(target=thread2_task)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
解決方式
- 統一鎖定順序:確保所有執行緒依相同順序取得鎖。
- 設定鎖定超時:使用
acquire(timeout=1)
等方法避免無限等待。
lock1.acquire(timeout=1)
2. 最佳化執行緒數量
啟動過多的執行緒會增加系統負擔,導致效能下降。應根據任務類型與硬體資源,選擇最合適的執行緒數量。
一般建議
- I/O 密集型任務:可以使用較多的執行緒,例如 CPU 核心數的兩倍以上。
- CPU 密集型任務:執行緒數應與 CPU 核心數相同或更少,以避免過度切換。
3. 安全地結束執行緒
正確地終止執行緒有助於保持程式的穩定性與可預測性。Python 的 threading
模組不支援強制終止執行緒,因此應在執行緒內部自行監控退出條件。
安全結束執行緒的範例
import threading
import time
class SafeThread(threading.Thread):
def __init__(self):
super().__init__()
self._stop_event = threading.Event()
def run(self):
while not self._stop_event.is_set():
print("執行緒運行中...")
time.sleep(1)
def stop(self):
self._stop_event.set()
thread = SafeThread()
thread.start()
time.sleep(5)
thread.stop()
thread.join()
print("執行緒已安全結束。")
重點說明
- 透過旗標或
Event
機制讓執行緒自行判斷是否結束。 - 使用
stop()
方法觸發終止訊號,並搭配join()
等待結束。
4. 使用日誌(logging)進行除錯
要追蹤執行緒中的行為,建議使用 logging
模組來記錄訊息。相較於 print
,logging
可提供執行緒名稱、時間戳記等更豐富的除錯資訊。
日誌設定範例
import threading
import logging
logging.basicConfig(level=logging.DEBUG, format='%(threadName)s: %(message)s')
def task():
logging.debug("任務開始")
logging.debug("任務完成")
thread = threading.Thread(target=task, name="MyThread")
thread.start()
thread.join()
重點說明
- 透過
name
指定執行緒名稱,便於在日誌中識別來源。 - 根據需求設定日誌等級(如 DEBUG、INFO、WARNING)以控制輸出內容。
5. 根據情境選擇執行緒或非同步處理
雖然執行緒非常適合處理 I/O 密集型任務,但在某些情況下,使用 asyncio
等非同步技術可能會更加高效。以下是兩者的適用情境比較:
- 適合使用執行緒的情況:
- 需要在 GUI 應用中處理背景任務
- 需要與其他執行緒或行程共享資料
- 適合使用非同步處理的情況:
- 需同時處理大量 I/O 任務(如網路請求)
- 任務流程簡單、不需複雜狀態管理
6. 保持設計簡潔
使用多執行緒雖然功能強大,但也容易讓程式變得複雜難維護。以下是設計多執行緒程式時應注意的原則:
- 盡量減少使用執行緒的數量,避免過度設計。
- 清楚定義每個執行緒的職責,讓程式結構清晰。
- 儘量避免共享資料,必要時建議使用佇列(Queue)等方式進行資料傳遞。

8. 總結
Python 的執行緒是一項強大工具,可用來提升程式的效率與反應速度。本文從基礎到進階應用,全面解析了如何在 Python 中有效地使用執行緒。以下為重點整理:
本文重點
- 執行緒的基本概念
- 執行緒是在同一行程中可獨立運作的單位,適用於並行處理。
- 了解並行(concurrent)與並列(parallel)的差異,有助於選擇正確技術。
- Python 中建立執行緒的方法
- 使用
threading
模組即可快速建立與控制執行緒。 - 透過
start()
與join()
控制執行緒執行流程。 - 可自訂類別進行進階管理與彈性擴充。
- 執行緒之間的同步
- 透過
Lock
、RLock
、Semaphore
等同步機制,避免資料競爭。 - 使用
Event
或 timeout 控制機制進行更精緻的流程管理。
- GIL(全域直譯器鎖)的影響
- GIL 限制 Python 執行緒在 CPU 密集型任務中的效能。
- I/O 任務仍非常適合使用執行緒;CPU 任務則推薦使用多行程或 C 擴充模組。
- 實作範例
- 透過網頁爬蟲、檔案操作、GUI 背景處理、即時資料分析等實例,展示執行緒的實用性。
- 最佳實踐
- 注意死結、控制執行緒數量、妥善處理終止流程與除錯日誌,確保程式穩定性與可維護性。
使用執行緒時應有的心態
- 執行緒不是萬靈丹
不當使用反而會降低效能,務必依任務類型選擇最合適的處理方式。 - 保持設計簡單
執行緒過多會讓系統與程式邏輯複雜化,應維持明確分工與簡潔設計。 - 靈活選擇替代方案
根據情況,asyncio
或multiprocessing
等方案可能更合適。
下一步建議
當你掌握了執行緒的基本技巧後,可以進一步學習下列主題:
- 非同步程式設計
- 學習
asyncio
模組,在單一執行緒中有效處理多個任務。
- 多行程處理
- 使用
multiprocessing
模組,處理 CPU 密集型任務,突破 GIL 限制。
- 進階執行緒控制
- 學習使用執行緒池(如
ThreadPoolExecutor
)與除錯工具,進一步優化執行緒管理。
- 應用於實際專案
- 試著開發具備多執行緒功能的專案,例如網路爬蟲、即時監控系統等,提升實戰經驗。
結語
只要妥善設計與管理,Python 執行緒將成為你打造高效並行程式的重要利器。希望本文能幫助你踏出穩健的一步!