按启动顺序回收
使用executor.map实现按顺序回收结果
Executor.map函数易于使用, 有一个特性:这个函数返回结果的顺序与调用开始的顺序一致。如果第一个调用生成结果用时10秒, 而其他调用只用 1 秒, 代码会阻塞 10 秒, 获取map方法返回的生成器产出的第一个结果。在此之后,获取后续结果时不会阻塞, 因为后续的调用已经结束
以下用例实现了使用线程池获取a*b的结果,并将结果以队列形式存储在res_lists中
res_lists = Queue() # 以队列的方式收集结果列表
def TheradPoolExample():
# 创建一个有7个线程的线程池
with ThreadPoolExecutor(max_workers=7) as executor:
# 每个用例作为一个线程的执行单位,用例参数存储在case_lists中
case_lists = []
for i in range(10):
casename = i
parameter = [i*10,i*10+1] # fuc函数包含多个参数,以列表的形式传递
case_ists.append(parameter) # 加入当前用例所需的参数
# 提交任务到线程池,按顺序收集结果
for t in case_lists:
task = executor.map(fuc, [t]) # map中第二个参数为可迭代参数,因此将parameter转为列表形式
for res in task:
res_lists.put(res) # 将结果加入到结果集中,此时顺序与启动线程顺序一致
return res_lists
# 线程需要处理的函数
def fuc(t):
a = t[0]
b = t[1]
return a+b
result = TheradPoolExample() # 调用线程池函数,可以遍历result验证是否是按开启顺序收集结果
按返回顺序回收
如果不关注线程的启动顺序,只需要收集结果的话,使用submit+as_complete,实现谁先完成就返回谁
submit将使用空闲线程去执行函数,一旦某个线程结束返回,则使用as_complete立即收集结果
同样的,以下用例实现了使用线程池获取a*b的结果,并将结果以队列形式存储在res_lists中
res_lists = Queue() # 以队列的方式收集结果列表
def TheradPoolExample():
# 创建一个有7个线程的线程池
with ThreadPoolExecutor(max_workers=7) as executor:
# 每个用例作为一个线程的执行单位,用例参数存储在case_lists中
case_lists = []
for i in range(10):
casename = i
parameter = [i*10,i*10+1] # fuc函数包含多个参数,以列表的形式传递
case_ists.append(parameter) # 加入当前用例所需的参数
# 获取每个测试用例的参数
for t in case_lists:
# 将任务提交到线程池
task = executor.submit(LogPaser, t)
tasks.append(task)
# 等待所有线程结束,也可不使用
executor.shutdown(wait=True)
# 获取线程返回结果,谁先完成谁就被优先获取
for future in concurrent.futures.as_completed(tasks):
updated_obj = future.result() # updated_obj为每个线程的结果
res_lists.put(updated_obj)
return res_lists
# 线程需要处理的函数
def fuc(t):
a = t[0]
b = t[1]
return a+b
result = TheradPoolExample() # 调用线程池函数,可以遍历result验证是否是按返回顺序收集结果
参考:
《fluent python》第 17 章 使用concurrent.futures处理并发
Python concurrent.futures 的 map 函数解释_python concurrent map-CSDN博客