Python - 中斷線程
大家好,有志於成為 Python 程式設計師的你!今天,我們將深入探討一個令人興奮的主題:在 Python 中中斷線程。如果你是程式設計的新手,也別擔心;我會一步步引導你完成這段旅程,就像過去多年教學中,我對無數學生所做的那樣。讓我們一起展開這次冒險吧!
線程是什麼?
在我們跳進中斷線程的主題之前,先快速回顧一下線程是什麼。想像你正在讀一本書(主程序),突然想起你需要打電話。你標記了你的頁面(創建一個線程),打了電話,然後回到你的書上。這就是線程在程式設計中的工作方式——它們允許程序同時進行多項工作。
線程中斷
現在,假設你正在打電話,但電話打得有點久,你想回到你的書上。你如何禮貌地結束通話?這就是線程中斷的用處。在 Python 中,我們有幾種方法可以做到這一點:
- 使用事件對象
- 使用旗標
讓我們透過一些有趣的例子來探索這兩種方法!
使用事件對象中斷線程
事件對象就像一個可以設定或清除的旗標。當旗標被設定時,它會向線程發出停止的信號。
以下是一個簡單的例子:
import threading
import time
def worker(event):
while not event.is_set():
print("工作中...")
time.sleep(1)
print("工作線程:我完成了!")
# 創建一個事件對象
stop_event = threading.Event()
# 創建並啟動線程
thread = threading.Thread(target=worker, args=(stop_event,))
thread.start()
# 讓線程運行 5 秒鐘
time.sleep(5)
# 設定事件以信號線程停止
stop_event.set()
# 等待線程完成
thread.join()
print("主程序:全部完成!")
讓我們來解析一下:
- 我們導入了必要的模組:
threading
用於處理線程,time
用於添加延時。 - 我們定義了一個
worker
函數,該函數在事件被設定之前會一直工作。 - 我們創建了一個名為
stop_event
的Event
對象。 - 我們創建並啟動一個線程,將
stop_event
傳遞給它。 - 我們使用
time.sleep(5)
讓線程運行 5 秒鐘。 - 我們使用
stop_event.set()
設定事件,這會向線程發出停止的信號。 - 我們使用
thread.join()
等待線程完成。
當你運行這個程序時,你會看到 "工作中..." 被打印出來好幾次,然後是 "工作線程:我完成了!",接著是 "主程序:全部完成!"。
使用旗標中斷線程
中斷線程的另一種方法是使用簡單的布林旗標。這種方法比較手動,但非常有效。
以下是一個例子:
import threading
import time
def counting_sheep(stop_flag):
count = 0
while not stop_flag[0]:
count += 1
print(f"數羊:{count}")
time.sleep(1)
print(f"我數了 {count} 棵羊才睡著!")
# 創建一個可變對象來保存我們的旗標
stop_flag = [False]
# 創建並啟動線程
thread = threading.Thread(target=counting_sheep, args=(stop_flag,))
thread.start()
# 讓線程數羊數 5 秒鐘
time.sleep(5)
# 將旗標設為 True 以停止線程
stop_flag[0] = True
# 等待線程完成
thread.join()
print("主程序:甜蜜的夢鄉!")
讓我們分析一下這段代碼:
- 我們定義了一個
counting_sheep
函數,該函數會計數直到stop_flag
被設為 True 為止。 - 我們創建了一個包含單個布林元素的列表
stop_flag
。我們使用列表是因為它是可變的,允許我們從線程外部修改它。 - 我們創建並啟動一個線程,將
stop_flag
傳遞給它。 - 我們讓線程數羊數 5 秒鐘。
- 我們將
stop_flag[0]
設為 True,向線程發出停止的信號。 - 我們使用
thread.join()
等待線程完成。
當你運行這個程序時,你會看到羊的數量增加大約 5 秒鐘,然後是最後的計數,接著是 "主程序:甜蜜的夢鄉!"。
方法比較
讓我們比較這兩種方法:
方法 | 优點 | 缺點 |
---|---|---|
事件對象 | - 內建同步 - 清晰且符合 Python 風格 |
- 需要傳遞事件對象 |
旗標 | - 簡單易於實現 - 不需要額外的對象 |
- 手動同步 - 可能出現競態條件 |
結論
恭喜你!你剛剛學會了兩種在 Python 中中斷線程的方法。事件對象方法通常因其內建同步而受到青睞,但旗標方法在更簡單的情境中也可能非常有用。
記住,就像禮貌地結束電話一樣,給你的線程機會清理一下再停止是很重要的。在現實世界的應用中,你可能需要在你的線程函數中添加一些清理代碼,這些代碼在收到停止信號時會運行。
程式設計就是實踐,所以我要鼓勵你實驗這些例子。試著修改它們,也許是添加多個線程或更改時間。誰知道呢?你或許能創造出一個有趣的 "中斷數羊遊戲"!
快樂編程,願你的線程總是能夠協調合作!
Credits: Image by storyset