多线程

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 是一个表示异步操作的对象,存储了任务的执行状态和结果。
  • 它由 ThreadPoolExecutorProcessPoolExecutorsubmit 方法返回,用于跟踪单个任务的状态。
主要属性和方法
  1. 状态相关

    • future.done():返回布尔值,任务是否已完成。
    • future.running():返回布尔值,任务是否正在运行。
    • future.cancelled():返回布尔值,任务是否被取消。
  2. 结果相关

    • future.result(timeout=None):
      
      • 获取任务的结果。如果任务未完成,会阻塞直到任务完成或超时。
      • 如果任务抛出异常,result 会重新抛出该异常。
    • future.exception(timeout=None):
      
      • 获取任务抛出的异常对象(如果有),否则返回 None
    • future.add_done_callback(fn):
      
      • 当任务完成时,调用指定的回调函数 fn
  3. 取消任务

    • future.cancel():尝试取消任务(仅对未开始的任务有效)。

2. as_completed 函数

  • as_completedconcurrent.futures 模块中的一个函数,用于同时监控多个 future 对象。
  • 它接受一个可迭代的 futures 列表,返回一个生成器,按任务完成的顺序依次提供已完成的 future 对象。
关键特性
  1. 按完成顺序返回
    • 与提交任务的顺序无关,任务完成后即可被处理。
    • 避免按顺序等待所有任务完成(相较于使用 wait 方法)。
  2. 非阻塞
    • 它本身不会阻塞,但通过迭代生成器可以按需处理已完成任务。

两者的关系

  • 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 添加回调函数处理单个任务 不直接支持回调,但结合生成器可逐个处理已完成任务
posted @ 2024-11-18 17:41  XieBuWan  阅读(1)  评论(0编辑  收藏  举报