Python 多线程完整入门
一、核心特点
- Python 多线程受 GIL 全局解释器锁限制:同一时刻只有1个线程执行 CPU 任务
- 适合:IO密集型(网络请求、文件读写、等待接口、爬虫)
- 不适合:CPU密集型(计算密集用多进程)
- 模块:内置
threading、_thread(低级)
二、两种创建线程方式
方式1:函数式(最常用)
import threading
import timedef task(name, delay):print(f"线程 {name} 启动,延迟 {delay}s 执行")time.sleep(delay)print(f"线程 {name} 执行完毕")if __name__ == "__main__":t1 = threading.Thread(target=task, args=("A", 2))t2 = threading.Thread(target=task, args=("B", 1))# 启动线程t1.start()t2.start()# 等待线程结束t1.join()t2.join()print("所有线程结束")
方式2:继承类
import threading
import timeclass MyThread(threading.Thread):def __init__(self, name, delay):super().__init__()self.name = nameself.delay = delaydef run(self):print(f"线程 {self.name} 启动")time.sleep(self.delay)print(f"线程 {self.name} 结束")if __name__ == "__main__":t1 = MyThread("A", 2)t2 = MyThread("B", 1)t1.start()t2.start()t1.join()t2.join()
三、守护线程 daemon
- 守护线程:主线程退出,守护线程直接强制结束,不等待
- 非守护线程(默认):主线程会等所有子线程跑完
t = threading.Thread(target=task, args=("A", 2), daemon=True)
四、线程安全:锁 Lock
多线程共享全局变量会资源竞争、数据错乱,用锁解决:
import threadingnum = 0
lock = threading.Lock()def add():global numfor _ in range(100000):lock.acquire() # 加锁try:num += 1finally:lock.release() # 释放锁if __name__ == "__main__":t1 = threading.Thread(target=add)t2 = threading.Thread(target=add)t1.start()t2.start()t1.join()t2.join()print(num)
五、线程池 ThreadPoolExecutor(推荐)
不用手动管理线程,自动复用,适合批量任务
from concurrent.futures import ThreadPoolExecutor
import timedef task(idx):print(f"任务 {idx} 开始")time.sleep(1)return f"任务 {idx} 完成"if __name__ == "__main__":# 最大5个线程并发with ThreadPoolExecutor(max_workers=5) as executor:# 提交10个任务tasks = [executor.submit(task, i) for i in range(10)]# 获取结果for res in tasks:print(res.result())
六、多线程 vs 多进程
| 类型 | 适用场景 | GIL | 开销 | 共享数据 |
|---|---|---|---|---|
| 多线程 | IO密集 | 有GIL,串行CPU | 小 | 直接共享 |
| 多进程 | CPU密集 | 无GIL,并行 | 大 | 需要队列/管道 |
七、总结
- IO 多任务优先用 threading / 线程池
- 计算密集直接上 multiprocessing 多进程
- 共享变量一定要加 Lock 保证线程安全
- 开发优先用
ThreadPoolExecutor更简洁稳定
