多线程
future 和 as_completed 的结合使用
from concurrent.futures import ThreadPoolExecutor, as_completed
def download_file(url):
# 模拟下载
import time
time.sleep(1)
return f"Downloaded {url}"
urls = ["file1", "file2", "file3"]
with ThreadPoolExecutor(max_workers=2) as executor:
futures = {executor.submit(download_file, url): url for url in urls}
for future in as_completed(futures):
url = futures[future]
try:
result = future.result()
print(f"Successfully downloaded {url}: {result}")
except Exception as e:
print(f"Error downloading {url}: {e}")
输出:
Successfully downloaded file1: Downloaded file1
Successfully downloaded file2: Downloaded file2
Successfully downloaded file3: Downloaded file3
future 和 as_completed 的区别与作用
1. future 对象
future
是一个表示异步操作的对象,存储了任务的执行状态和结果。- 它由
ThreadPoolExecutor
或ProcessPoolExecutor
的submit
方法返回,用于跟踪单个任务的状态。
主要属性和方法
-
状态相关
future.done()
:返回布尔值,任务是否已完成。future.running()
:返回布尔值,任务是否正在运行。future.cancelled()
:返回布尔值,任务是否被取消。
-
结果相关
-
future.result(timeout=None):
- 获取任务的结果。如果任务未完成,会阻塞直到任务完成或超时。
- 如果任务抛出异常,
result
会重新抛出该异常。
-
future.exception(timeout=None):
- 获取任务抛出的异常对象(如果有),否则返回
None
。
- 获取任务抛出的异常对象(如果有),否则返回
-
future.add_done_callback(fn):
- 当任务完成时,调用指定的回调函数
fn
。
- 当任务完成时,调用指定的回调函数
-
-
取消任务
future.cancel()
:尝试取消任务(仅对未开始的任务有效)。
2. as_completed 函数
as_completed
是concurrent.futures
模块中的一个函数,用于同时监控多个future
对象。- 它接受一个可迭代的
futures
列表,返回一个生成器,按任务完成的顺序依次提供已完成的future
对象。
关键特性
- 按完成顺序返回
- 与提交任务的顺序无关,任务完成后即可被处理。
- 避免按顺序等待所有任务完成(相较于使用
wait
方法)。
- 非阻塞
- 它本身不会阻塞,但通过迭代生成器可以按需处理已完成任务。
两者的关系
- future:表示单个任务的状态和结果。
- as_completed:同时监控多个
future
,按完成顺序处理任务。
from concurrent.futures import ThreadPoolExecutor, as_completed
def task(n):
return n ** 2
with ThreadPoolExecutor(max_workers=3) as executor:
futures = [executor.submit(task, i) for i in range(5)]
# 使用 as_completed 处理任务完成
for future in as_completed(futures):
print(f"Task completed with result: {future.result()}")
输出:(完成顺序可能不同)
Task completed with result: 16
Task completed with result: 1
Task completed with result: 0
Task completed with result: 4
Task completed with result: 9
使用场景与对比
特性 | future | as_completed |
---|---|---|
监控对象 | 单个任务 | 多个任务 |
结果获取 | 调用 result() 获取任务的结果 |
按完成顺序返回 future 对象,逐个调用 result() |
适用场景 | 需要跟踪特定任务状态或结果 | 并发执行多个任务,按完成顺序处理结果 |
顺序 | 不涉及顺序 | 任务完成顺序(与提交顺序无关) |
回调支持 | 可通过 add_done_callback 添加回调函数处理单个任务 |
不直接支持回调,但结合生成器可逐个处理已完成任务 |