Python 并发中:as_completed() 函数

as_completed() 是 Python 并发编程中一个非常实用的函数,它的作用是:按照任务完成的顺序,而不是提交的顺序,来返回结果

一、核心区别

场景对比

假设提交了 3 个任务,执行时间分别是:任务1(3秒)、任务2(1秒)、任务3(2秒)

方法 返回顺序 等待时间
as_completed() 先完成的先返回:任务2 → 任务3 → 任务1 总耗时约 3 秒
wait() + 手动取结果 按提交顺序返回:任务1 → 任务2 → 任务3 总耗时约 3 秒
复制代码
from concurrent.futures import ThreadPoolExecutor, as_completed
import time

def task(name, delay):
    time.sleep(delay)
    return f"{name} 完成"

with ThreadPoolExecutor() as executor:
    # 提交三个任务
    futures = []
    futures.append(executor.submit(task, "任务A", 3))
    futures.append(executor.submit(task, "任务B", 1))
    futures.append(executor.submit(task, "任务C", 2))
    
    # 方式1:as_completed - 按完成顺序
    print("=== as_completed ===")
    for f in as_completed(futures):
        print(f.result())
    # 输出顺序:任务B完成 → 任务C完成 → 任务A完成
    
    # 方式2:直接遍历 - 按提交顺序(会阻塞)
    print("=== 直接遍历 ===")
    for f in futures:
        print(f.result())  # 任务A还没完成,会等待3秒
    # 输出顺序:任务A完成 → 任务B完成 → 任务C完成

二、工作原理

源码简化

复制代码
def as_completed(fs, timeout=None):
    """按完成顺序返回 Future"""
    fs = set(fs)
    while fs:
        # 等待任何一个 Future 完成
        done, _ = wait(fs, return_when=FIRST_COMPLETED)
        for future in done:
            yield future
            fs.remove(future)

三、与其他方法的对比

方法 返回方式 阻塞特性 适用场景
for f in futures: f.result() 按提交顺序 遇到未完成就阻塞 必须按顺序处理结果
as_completed(futures) 按完成顺序 立即返回已完成的结果 结果处理顺序不重要
wait(futures) 等待全部/任一完成 阻塞直到条件满足 需要批量等待
gather(*futures) 按提交顺序返回列表 等待全部完成 需要一次性获取所有结果

备注: 其实as_completed 的意思就是:谁先做完,谁先被处理,不管当初谁先排队。