最近在celery源码学习中经常看到event库的使用,想结合源码学习,重温threading.event()的使用
threading.Event
是 Python 标准库 threading
模块中的一个线程同步原语,用于线程间的等待与通知。它允许一个或多个线程等待某个"事件"发生(即事件被 set),而其它线程可以在合适的时机触发该事件。常用于线程间通信、同步、生产者-消费者等场景。
主要特性
- 事件标志:内部维护一个布尔标志,初始为 False。
- set():将事件标志设为 True,唤醒所有等待的线程。
- clear():将事件标志设为 False,等待的线程会阻塞。
- wait(timeout=None):阻塞当前线程,直到事件标志为 True 或超时。
- is_set():查询事件标志当前状态。
1. 基本等待与通知
python
import threading
import time
event = threading.Event()
def worker():
print("Worker: 等待事件...")
event.wait()
print("Worker: 事件已触发,开始工作!")
t = threading.Thread(target=worker)
t.start()
time.sleep(2)
print("主线程: 2秒后触发事件")
event.set()
t.join()
输出:
makefile
Worker: 等待事件...
主线程: 2秒后触发事件
Worker: 事件已触发,开始工作!
2. 多线程同时等待同一个事件
python
import threading
import time
event = threading.Event()
def worker(n):
print(f"Worker {n}: 等待事件...")
event.wait()
print(f"Worker {n}: 事件已触发,开始工作!")
threads = [threading.Thread(target=worker, args=(i,)) for i in range(3)]
for t in threads: t.start()
time.sleep(1)
print("主线程: 1秒后触发事件")
event.set()
for t in threads: t.join()
输出:
yaml
Worker 0: 等待事件...
Worker 1: 等待事件...
Worker 2: 等待事件...
主线程: 1秒后触发事件
Worker 0: 事件已触发,开始工作!
Worker 1: 事件已触发,开始工作!
Worker 2: 事件已触发,开始工作!
3. 超时等待
python
import threading
import time
event = threading.Event()
def worker():
print("Worker: 最多等待3秒...")
flag = event.wait(timeout=3)
if flag:
print("Worker: 事件已触发!")
else:
print("Worker: 超时未触发事件,继续执行...")
t = threading.Thread(target=worker)
t.start()
time.sleep(5)
event.set()
t.join()
输出:
makefile
Worker: 最多等待3秒...
Worker: 超时未触发事件,继续执行...
4. 多次触发与清除
python
import threading
import time
event = threading.Event()
def worker():
while True:
print("Worker: 等待事件...")
event.wait()
print("Worker: 事件已触发,工作一次!")
event.clear() # 清除事件,进入下一轮等待
t = threading.Thread(target=worker, daemon=True)
t.start()
for i in range(3):
time.sleep(1)
print(f"主线程: 第{i+1}次触发事件")
event.set()
time.sleep(2)
输出:
makefile
Worker: 等待事件...
主线程: 第1次触发事件
Worker: 事件已触发,工作一次!
Worker: 等待事件...
主线程: 第2次触发事件
Worker: 事件已触发,工作一次!
Worker: 等待事件...
主线程: 第3次触发事件
Worker: 事件已触发,工作一次!
Worker: 等待事件...
5. 生产者-消费者模型(事件控制)
python
import threading
import time
event = threading.Event()
data = []
def producer():
for i in range(5):
time.sleep(1)
data.append(i)
print(f"Producer: 生产数据 {i}")
event.set() # 通知消费者有新数据
event.clear()
def consumer():
for _ in range(5):
print("Consumer: 等待新数据...")
event.wait()
print(f"Consumer: 消费数据 {data[-1]}")
t1 = threading.Thread(target=producer)
t2 = threading.Thread(target=consumer)
t1.start()
t2.start()
t1.join()
t2.join()
输出:
makefile
Consumer: 等待新数据...
Producer: 生产数据 0
Consumer: 消费数据 0
Consumer: 等待新数据...
Producer: 生产数据 1
Consumer: 消费数据 1
Consumer: 等待新数据...
Producer: 生产数据 2
Consumer: 消费数据 2
Consumer: 等待新数据...
Producer: 生产数据 3
Consumer: 消费数据 3
Consumer: 等待新数据...
Producer: 生产数据 4
Consumer: 消费数据 4
总结
threading.Event
适合多线程同步、等待、通知、超时等场景。- 通过 set/clear/wait/is_set 方法实现灵活的线程间通信。
- 可用于生产者-消费者、批量唤醒、超时控制等多种并发模式。