CPU密集型任务用进程池,IO密集型用线程池;混合场景可组合使用,小任务宜同步执行,资源受限时需合理设置池大小。

选线程池还是进程池,关键看任务类型:CPU密集型用进程池,IO密集型用线程池。
看任务是否频繁等待外部资源
如果任务大量时间花在等待网络响应、文件读写、数据库查询等操作上,属于IO密集型。这类任务线程切换开销小,GIL影响不大,用ThreadPoolExecutor更轻量、启动快、内存占用低。比如并发请求100个网页,用线程池通常比进程池快2–3倍。
- 典型场景:HTTP请求、日志写入、Redis操作、CSV解析(含读取)
- 注意点:单个IO操作若耗时极长(如超30秒),需设timeout并捕获异常,避免线程卡死
看任务是否持续占用CPU计算
如果任务主要做数学运算、图像处理、加密解密、大规模列表推导等,属于CPU密集型。Python的GIL会限制多线程真正并行,此时ProcessPoolExecutor能绕过GIL,利用多核提升吞吐。但进程启动慢、内存复制开销大,不适合短任务或数据量大的参数传递。
- 典型场景:科学计算、视频帧处理、批量PDF文本提取、蒙特卡洛模拟
- 注意点:传参尽量轻量;复杂对象建议用
functools.partial或封装成可序列化函数
混合场景可以组合使用
实际项目常同时存在IO和CPU操作。例如“下载图片→本地缩略图处理”,可先用线程池并发下载,再将下载好的文件路径交给进程池做CPU密集的图像处理。避免在线程中直接调用CPU-heavy函数,否则会阻塞整个线程池。
立即学习“Python免费学习笔记(深入)”;
- 推荐结构:线程池负责IO部分,结果通过队列或列表交由进程池二次处理
- 不推荐:在线程里调
subprocess.run()启动新进程——管理复杂且易出错
别忽略小任务和资源限制
任务平均执行时间低于10ms,或总并发数不到5,用同步执行反而更稳。盲目上池子可能因调度开销得不偿失。另外,进程池数量不宜超过os.cpu_count(),线程池一般控制在min(32, os.cpu_count() * 4)以内,避免系统级线程/进程竞争。
- 调试技巧:用
concurrent.futures.as_completed()观察各任务耗时分布,识别瓶颈类型 - 替代思路:对极高并发IO(如万级连接),考虑
asyncio+aiohttp,比线程池更省内存










