基础代码

with ThreadPoolExecutor(max_workers=3) as executor:
    # 进入这个代码块时,线程池立即创建并准备好
    # 这里不会阻塞,可以立即提交任务
    
    # 提交任务(非阻塞)
    future1 = executor.submit(task1)
    future2 = executor.submit(task2)
    
    # 其他代码会立即执行
    print("这行代码会立即执行,不会等待任务完成")

# 当退出 with 代码块时,会调用 executor.shutdown(wait=True)
# 这里才会阻塞,等待所有线程执行完成
print("所有线程执行完成后才会执行这行")

with结束的时候会被阻塞

这就要说with的基本语法

with 上下文管理器 as 变量:
    # 使用资源的代码块
# 自动清理资源

上面代码等驾于

管理器 = 上下文管理器()
变量 = 管理器.__enter__()
try:
    # 使用资源的代码块
finally:
    管理器.__exit__()

ThreadPoolExecutor的做法是

class ThreadPoolExecutor:
    def __enter__(self):
        return self  # 返回 executor 对象本身
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.shutdown(wait=True)  # 这就是隐式调用的地方

self.shutdown(wait=True)会造成阻塞,等待所有任务执行完成

如果在with块内就需要阻塞

# 方法1:手动控制关闭
executor = ThreadPoolExecutor(max_workers=3)
futures = [executor.submit(task, i) for i in range(5)]
# 手动等待特定任务
result = futures[0].result()
executor.shutdown(wait=False)  # 不等待立即关闭

# 方法2:使用 as_completed 按完成顺序处理
with ThreadPoolExecutor(max_workers=3) as executor:
    futures = [executor.submit(task, i) for i in range(5)]
    
    # 不等待所有任务,按完成顺序处理
    for future in as_completed(futures):
        result = future.result()
        print(f"完成: {result}")

future.result()会造成阻塞

这里注意一下as_completed并不会使任务按照顺序返回,哪个任务先执行完,上面代码先输出哪个任务的结果

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐