python threading库中,start()、join()方法的用法是什么?daemo参数的含义是什么?
我来详细解释 Python threading 库中的这些重要概念。
start() 方法
start() 方法用于启动线程,使其开始执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import threading import time
def worker(): print("线程开始执行") time.sleep(2) print("线程执行完毕")
t = threading.Thread(target=worker)
t.start()
print("主线程继续执行")
|
特点:
- 每个线程只能调用一次
start()
- 调用后线程进入就绪状态,等待 CPU 调度
- 立即返回,不会阻塞主线程
join() 方法
join() 方法用于等待线程执行完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import threading import time
def worker(name): print(f"{name} 开始工作") time.sleep(2) print(f"{name} 工作完成")
t1 = threading.Thread(target=worker, args=("线程1",)) t2 = threading.Thread(target=worker, args=("线程2",))
t1.start() t2.start()
print("主线程等待子线程完成...")
t1.join() t2.join()
print("所有线程执行完毕")
|
带超时的 join:
1 2 3 4 5 6
| t1.join(timeout=1.0) if t1.is_alive(): print("线程仍在运行,超时了") else: print("线程已完成")
|
daemon 参数
daemon(守护线程)参数决定线程是否随主线程结束而强制结束。
非守护线程 (daemon=False,默认值)
1 2 3 4 5 6 7 8 9 10 11 12
| import threading import time
def worker(): print("非守护线程开始") time.sleep(3) print("非守护线程结束")
t = threading.Thread(target=worker, daemon=False) t.start()
print("主线程结束")
|
守护线程 (daemon=True)
1 2 3 4 5 6 7 8 9 10 11 12
| import threading import time
def worker(): print("守护线程开始") time.sleep(3) print("守护线程结束")
t = threading.Thread(target=worker, daemon=True) t.start()
print("主线程结束")
|
完整示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import threading import time
def worker(name, delay, is_daemon): print(f"{name} 开始执行 (daemon={is_daemon})") time.sleep(delay) print(f"{name} 执行完成 (daemon={is_daemon})")
daemon_thread = threading.Thread( target=worker, args=("守护线程", 3, True), daemon=True )
normal_thread = threading.Thread( target=worker, args=("非守护线程", 2, False), daemon=False )
daemon_thread.start() normal_thread.start()
print("主线程继续执行...") time.sleep(1) print("主线程等待非守护线程...")
normal_thread.join()
print("主线程结束")
|
关键点总结
| 方法/参数 |
作用 |
说明 |
start() |
启动线程 |
线程开始执行,立即返回 |
join() |
等待线程完成 |
阻塞调用线程直到目标线程完成 |
daemon=True |
设置为守护线程 |
主线程结束时强制终止该线程 |
daemon=False |
设置为非守护线程 |
主线程会等待该线程完成 |
使用建议:
- 对于需要在后台运行但不重要的任务,使用守护线程
- 对于需要确保完成的重要任务,使用非守护线程
- 使用
join() 来控制线程执行顺序和同步
Event的set()和is_set()方法的原理和用法?
我来详细讲解 threading.Event 的 set() 和 is_set() 方法的原理和用法。
Event 的基本概念
Event 是一个简单的线程同步工具,它内部维护一个标志位,线程可以等待这个标志位被设置。
核心方法
set() 方法
- 作用:将 Event 的内部标志设置为
True
- 效果:唤醒所有等待该 Event 的线程
- 特点:一旦设置为
True,会一直保持,直到手动清除
is_set() 方法
- 作用:检查 Event 的内部标志是否为
True
- 返回值:
True 或 False
- 特点:非阻塞,立即返回当前状态
其他重要方法
clear():将标志重置为 False
wait(timeout=None):阻塞直到标志为 True 或超时
用法示例
基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import threading import time
event = threading.Event()
def worker(name): print(f"{name} 等待事件触发...") event.wait() print(f"{name} 检测到事件,继续执行")
threads = [] for i in range(3): t = threading.Thread(target=worker, args=(f"线程-{i}",)) t.start() threads.append(t)
print("主线程:3秒后触发事件") time.sleep(3)
print("主线程:设置事件") event.set()
for t in threads: t.join()
print("所有线程执行完毕")
|
使用 is_set() 检查状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import threading import time
event = threading.Event()
def status_checker(): while True: if event.is_set(): print("事件已触发,执行任务...") time.sleep(1) else: print("事件未触发,等待中...") time.sleep(0.5) if event.is_set() and some_condition: break
def trigger(): time.sleep(2) print("触发器:设置事件") event.set()
threading.Thread(target=status_checker).start() threading.Thread(target=trigger).start()
|
一次性事件模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import threading import time
class TaskCoordinator: def __init__(self): self.start_event = threading.Event() self.complete_event = threading.Event() def worker(self, name): print(f"{name} 等待开始信号...") self.start_event.wait() print(f"{name} 开始工作...") time.sleep(2) print(f"{name} 工作完成") self.complete_event.set() def start_workers(self, num_workers): workers = [] for i in range(num_workers): t = threading.Thread(target=self.worker, args=(f"Worker-{i}",)) t.start() workers.append(t) time.sleep(1) print("协调器:开始所有工作线程") self.start_event.set() self.complete_event.wait() print("协调器:所有工作线程已完成")
coordinator = TaskCoordinator() coordinator.start_workers(3)
|
超时等待示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import threading import time
event = threading.Event()
def waiter(name, timeout): print(f"{name} 开始等待,超时时间: {timeout}秒") if event.wait(timeout=timeout): print(f"{name} 成功等到事件") else: print(f"{name} 等待超时")
def setter(): time.sleep(2) print("Setter: 设置事件") event.set()
threading.Thread(target=waiter, args=("快速等待", 1)).start() threading.Thread(target=waiter, args=("正常等待", 3)).start() threading.Thread(target=setter).start()
|
重复使用 Event
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import threading import time
class ReusableEvent: def __init__(self): self.event = threading.Event() def worker(self, name): for i in range(3): print(f"{name} 第{i+1}次等待...") self.event.wait() print(f"{name} 第{i+1}次被唤醒") self.event.clear() def controller(self): for i in range(3): time.sleep(2) print(f"控制器:第{i+1}次触发") self.event.set() time.sleep(0.1)
reusable = ReusableEvent()
for i in range(2): threading.Thread(target=reusable.worker, args=(f"Worker-{i}",)).start()
controller_thread = threading.Thread(target=reusable.controller) controller_thread.start() controller_thread.join()
|
原理说明
- 内部标志:Event 内部维护一个布尔值标志
- set():将标志设为
True,并通知所有等待的线程
- is_set():立即返回当前标志状态,不阻塞
- wait():如果标志为
False则阻塞,为 True则立即返回
- clear():将标志重置为
False
使用场景
- 线程协调:一个线程通知多个线程开始执行
- 资源就绪通知:当某个资源准备好时通知等待线程
- 任务调度:控制多个线程的执行时机
- 系统状态管理:表示系统是否处于某种特定状态
Event 提供了一种简单而强大的线程间通信机制,特别适合”一触即发”的场景。