为何ThreadPoolExecutor运行耗时比threading模块更长?
以下是几个核心原因,你可以结合自己的代码逐一排查:
线程池的封装开销:ThreadPoolExecutor底层依赖
threading实现,但额外增加了任务队列管理、Future对象状态跟踪、线程池生命周期维护等逻辑。如果你的dummy函数执行时间极短(比如毫秒级),这些封装带来的额外开销占比会被放大,直接拉低整体效率。而直接使用threading.Thread时,没有这些额外的封装步骤,线程启动与执行的成本更低。线程数量配置差异:
ThreadPoolExecutor默认线程数等于CPU核心数(os.cpu_count()),但如果你的dummy函数是IO密集型(包含sleep、网络请求等阻塞操作),线程数越多,并行处理的效率越高。如果你手动用threading创建了更多线程(比如10+),而ThreadPoolExecutor沿用默认的4/8线程,前者的耗时自然会更短。任务等待方式的问题:
如果你用ThreadPoolExecutor.submit()提交任务后,循环调用future.result()等待结果,会按任务提交顺序逐个等待完成——虽然任务本身是并行执行的,但这种写法会让主线程串行等待每个任务的结果(若某个任务耗时更长,后续的result()仍会等待它)。而threading的写法通常是先启动所有线程,再统一join()等待全部完成,这种等待方式更高效。比如:# 这种写法可能因串行等待放大耗时 with ThreadPoolExecutor() as executor: futures = [executor.submit(dummy) for _ in range(10)] for f in futures: f.result()对比threading的写法:
threads = [threading.Thread(target=dummy) for _ in range(10)] for t in threads: t.start() for t in threads: t.join()线程初始化的一次性开销:ThreadPoolExecutor第一次初始化时,会批量创建线程池内的所有线程,这个过程的开销可能比逐个创建
threading.Thread更大。如果你的测试只运行了一次,刚好触发了这个初始化阶段,也会导致总耗时增加。
内容的提问来源于stack exchange,提问作者mehmed-i Rumi

