线程池适合i/o密集型任务,因i/o操作释放gil实现并发;进程池适合cpu密集型任务,可绕过gil实现多核并行;混合场景需分层调度,选错类型会导致性能下降。

线程池适合I/O密集型任务
网络请求、文件读写、数据库查询这类操作大部分时间在等待响应,CPU空闲。线程切换开销小,多个线程可以交替执行,把等待时间“叠”起来用,整体耗时明显下降。比如同时发起10个HTTP请求,用线程池通常比串行快好几倍。
注意:Python有GIL(全局解释器锁),同一时刻只有一个线程执行Python字节码。但I/O操作会自动释放GIL,所以线程能真正并发等待——这正是它高效的原因。
- 推荐用 concurrent.futures.ThreadPoolExecutor
- 控制最大线程数(如 max_workers=10),避免系统资源耗尽
- 避免在线程中做大量纯计算,否则GIL会让它们排队执行,失去并发意义
进程池适合CPU密集型任务
图像处理、数值计算、加密解密、机器学习训练等任务持续占用CPU。多线程受GIL限制,无法并行利用多核;而进程彼此独立,绕过GIL,可真正分摊到不同CPU核心上运行。
代价是内存占用高(每个进程复制一份解释器和数据)、启动稍慢、进程间通信不如线程直接。
立即学习“Python免费学习笔记(深入)”;
- 推荐用 concurrent.futures.ProcessPoolExecutor
- max_workers 一般设为 CPU 核心数(os.cpu_count())或略高
- 传入函数和参数必须能被序列化(pickle),不能是lambda或嵌套函数
别混淆“并发”和“并行”
并发指多个任务交替推进,适用于I/O场景;并行指多个任务真正同时执行,需要多核支持,适用于计算场景。线程池实现的是并发,进程池才可能实现并行。
选错会导致性能不升反降:用线程池跑CPU密集任务,速度可能比单线程还慢;用进程池跑高频小I/O请求,可能因进程开销抵消收益。
- 简单判断:任务中是否大量调用 time.sleep、requests.get、open?→ 倾向线程池
- 任务中是否大量循环、数学运算、pandas.apply、numpy-heavy 操作?→ 倾向进程池
实际项目中的混合策略
真实业务往往既有I/O又有计算。例如一个Web爬虫要下载网页(I/O),再解析HTML并提取数据(轻量计算),最后做统计聚合(较重计算)。这时可以分层处理:
- 用线程池抓取页面
- 把结果交给进程池做清洗或模型推理
- 主线程或单独线程汇总结果、写入数据库
concurrent.futures 支持 submit 和 as_completed,方便组合调度;也可搭配 asyncio(如 aiohttp + ProcessPoolExecutor)进一步优化吞吐。










