threading.Event适用于线程间简单信号通知场景,如启动门控、暂停恢复、任务完成通知;它仅传递布尔状态,不传数据、无顺序保证,需避免误用set/wait及忽略超时和clear。

threading.Event 什么时候该用?
当你需要一个线程“等某个信号”,而另一个线程负责“发信号”时,threading.Event 是最轻量、最直接的方案。它不传递数据,只传递“是/否”状态,适合做启动门控、暂停恢复、任务完成通知这类场景。别拿它当 queue.Queue 用——它不存值,也不保证顺序。
set() 和 wait() 的典型误用
常见错误是调用 wait() 前没检查 is_set(),导致线程在事件已被置位后仍阻塞;或者多个线程反复 set() 后没 clear(),造成后续 wait() 立即返回,逻辑错乱。
-
wait()默认无限等待,建议总带超时:e.wait(timeout=5),避免死锁 -
set()是“单次触发”,不是“持续有效”——除非你手动clear(),否则所有后续wait()都会立刻通过 - 多个线程同时
wait()没问题,但只有一个线程调用set()就能唤醒全部(不是只唤醒一个)
一个真实可用的启停控制示例
比如写一个后台采集线程,需响应外部指令随时暂停/继续:
import threading
import time
<p>stop_event = threading.Event()
pause_event = threading.Event()
pause_event.set() # 初始为运行状态</p><p>def collector():
while not stop_event.is_set():
if pause_event.wait(timeout=0.1): # 等待恢复信号,0.1秒轮询一次
print("采集中...")
time.sleep(1)
else:
print("已暂停")
print("采集结束")</p><p>t = threading.Thread(target=collector)
t.start()</p><p>time.sleep(3)
print("暂停采集")
pause_event.clear()</p><p>time.sleep(2)
print("恢复采集")
pause_event.set()</p><p>time.sleep(2)
stop_event.set()
t.join()</p>注意:pause_event.wait(timeout=0.1) 这里用短超时实现非阻塞轮询,避免 wait() 卡死无法响应 stop_event。
立即学习“Python免费学习笔记(深入)”;
和 condition / queue 相比差在哪?
threading.Event 不提供互斥保护,也不带数据。如果你需要“等某个条件成立且拿到结果”,用 threading.Condition 更合适;如果要传递具体数值或对象,必须换 queue.Queue。Event 的优势就是简单、快、内存开销小——但它只回答一个问题:“那个开关打开了吗?”
多线程里最易被忽略的是:Event 对象本身不是线程安全的“状态容器”,它的 set()/clear()/wait() 是原子的,但 is_set() 返回的瞬间状态可能立刻被其他线程改写。别靠它做复杂状态机,只用作信号旗。


















