You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API分块数据并行获取优化:避免创建不必要线程

动态控制任务提交,避免无效API请求

先唠唠你原代码的问题:一次性提交了所有maxBlocks的请求,哪怕某个块返回None,后面更大序号的请求已经发出去了,完全是浪费资源。要实现「检测到None后不再创建更大序号的任务」,得动态提交任务,不能一股脑把所有任务都扔给线程池。

优化思路

  • 不预先提交所有任务,先提交一批(数量和线程池大小一致)
  • 处理每个完成的请求时,跟踪当前的块序号
  • 一旦某个块返回None,立刻停手,不再提交更大序号的任务,甚至可以取消已经提交但还没跑完的、序号更大的任务
  • 没碰到None的话,就继续提交下一个序号的任务,直到把所有有效块都捞完

修正后的代码

def func(step):
    # 这里放你原有的API获取逻辑
    block = ...  # 从API拿对应step的块数据
    if len(block) == 0:
        return None
    else:
        return block

def fetch_all_blocks(maxBlocks):
    blocks_data = []
    stop_fetching = False
    next_step = 0
    max_workers = 10

    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 先提交第一批任务,数量和线程池一致
        futures = {}
        while next_step < min(maxBlocks, max_workers):
            future = executor.submit(func, next_step)
            futures[future] = next_step
            next_step += 1

        while futures:
            # 等任意一个任务跑完
            done, _ = concurrent.futures.wait(futures, return_when=concurrent.futures.FIRST_COMPLETED)
            for future in done:
                step = futures.pop(future)
                result = future.result()
                if result is not None:
                    blocks_data.extend(result)
                    # 还没到最大块数、也没触发停止的话,继续提交下一个任务
                    if not stop_fetching and next_step < maxBlocks:
                        next_future = executor.submit(func, next_step)
                        futures[next_future] = next_step
                        next_step += 1
                else:
                    # 碰到None了,标记停止,不再提交后续任务
                    stop_fetching = True
                    # 可选:取消已经提交但还没跑完的、序号比当前大的任务,进一步省资源
                    for pending_future, pending_step in list(futures.items()):
                        if pending_step > step:
                            pending_future.cancel()
                    # 清空剩余任务,提前结束循环
                    futures.clear()
                    break
    return blocks_data

代码说明

  1. 动态提交:一开始只提交和线程池大小相同的任务,避免资源瞬间占满,后续按需提交,更灵活
  2. 停止机制:一旦某个块返回None,立刻打住,不再提交新任务,还能取消已提交的无效任务(这个是可选操作,看你要不要省这点资源)
  3. 数据收集:用extend代替+=,处理列表时更高效
  4. 修正语法错误:你原代码里的futures = {executor.submit(func, step), i for i in range(maxBlocks)}是错的,这里用字典把每个future和对应的step绑定,方便跟踪是哪个块的请求

额外小技巧

  • 如果API允许,可以先请求一个偏后的块(比如maxBlocks的一半),快速找到边界,减少要提交的任务数量
  • 可以加个重试逻辑,避免因为网络波动导致某个块临时返回None,误判成没有数据

内容的提问来源于stack exchange,提问作者Martí Castell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:04:51