Python并发:等待多Future中一个返回True后取消其余任务
解决方案:用ThreadPoolExecutor实现“先完成且符合条件则终止其他任务”
刚好遇到过类似的场景,用concurrent.futures的as_completed()配合线程终止信号就能完美解决你的需求,直接上代码和解释:
核心思路
- 用
as_completed()实时监听任务完成状态,哪个任务先结束就先处理它的返回值 - 一旦拿到返回
True的结果,立刻给其他任务发送终止信号(因为线程无法强行终止,让任务主动退出更安全) - 尝试取消还未开始执行的任务(避免资源浪费)
完整代码示例
import concurrent.futures import time import random from threading import Event def long_running_task(stop_event): """模拟你的耗时任务:获取代理、发送HTTP请求等""" print("任务启动中...") # 模拟分步执行的耗时操作,方便中途检查终止信号 for step in range(5): # 每次执行步骤前检查是否需要终止 if stop_event.is_set(): print("任务收到终止指令,提前退出") return False # 模拟随机耗时(替换成你实际的业务逻辑) time.sleep(random.uniform(0.3, 1.5)) print(f"任务完成第 {step+1} 步") # 模拟业务返回结果(替换成你实际的返回判断逻辑) final_result = random.choice([True, False]) print(f"任务执行完毕,返回值: {final_result}") return final_result def main(): # 创建一个事件对象,用于跨线程传递终止信号 stop_signal = Event() with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: # 提交两个任务,把终止信号传入 task_futures = [ executor.submit(long_running_task, stop_signal), executor.submit(long_running_task, stop_signal) ] # 遍历已完成的任务 for completed_future in concurrent.futures.as_completed(task_futures): try: result = completed_future.result() if result is True: print("✅ 找到符合条件的任务结果,开始终止其他任务") # 触发终止信号,通知正在运行的任务主动退出 stop_signal.set() # 取消所有未完成的任务(仅对未启动的任务有效) for future in task_futures: if future != completed_future and not future.done(): future.cancel() # 跳出循环,进入后续流程 break except Exception as e: print(f"❌ 任务执行出错: {str(e)}") # 可根据需求决定是否终止其他任务,这里继续等待其他任务 # 后续业务流程 print("\n===== 进入后续代码逻辑 =====") # 这里写你的后续处理代码 if __name__ == "__main__": main()
关键细节解释
as_completed()方法:它会按任务完成的先后顺序返回Future对象,而不是按提交顺序,完美契合你“哪个先完成就先检查”的需求。threading.Event():这是线程安全的信号传递方式,因为Python的线程无法被强行终止(强行终止可能导致资源泄漏),所以让任务主动检查stop_signal的状态,是最安全的终止方式。Future.cancel():这个方法只能取消还处于pending状态(未被调度执行)的任务,如果任务已经在运行,cancel()会返回False,这时候就靠stop_signal让任务主动退出。- 异常处理:任务执行中可能出现请求失败、代理异常等错误,用
try-except包裹future.result()可以避免程序崩溃,同时你可以根据需求决定是否终止其他任务。
内容的提问来源于stack exchange,提问作者slashms
相关产品推荐
相关产品推荐

