从Python3.2开始,标准库为我们提供了concurrent.futures 模块,它提供了 ThreadPoolExecutor (线程池)和 ProcessPoolExecutor (进程池)两个类。

相比 threading 等模块,该模块通过 submit 返回的是一个 future 对象,它是一个未来可期的对象,通过它可以获取某一个线程执行的状态或者某一个任务执行的状态及返回值:

  1. 主线程可以获取某一个线程(或者任务的)的状态,以及返回值。
  2. 当一个线程完成的时候,主线程能够立即知道。

基础语法介绍

import time
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED,FIRST_COMPLETED, as_completed def action(second):
print(second)
time.sleep(second)
return second lists=[4,5,2,3] # 创建一个最大容纳数量为2的线程池
pool= ThreadPoolExecutor(max_workers=2) # 通过submit提交执行的函数到线程池中
all_task=[pool.submit(action, i) for i in lists] # 通过result来获取返回值
result=[i.result() for i in all_task]
print(f"result:{result}") print("----complete-----")
# 线程池关闭
pool.shutdown()

返回结果:

4
5
2
3
result:[4, 5, 2, 3]
----complete-----

使用上下文管理器

可以通过 with 关键字来管理线程池,当线程池任务完成之后自动关闭线程池。

import time
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED,FIRST_COMPLETED, as_completed def action(second):
print(second)
time.sleep(second)
return second lists=[4,5,2,3]
all_task = []
with ThreadPoolExecutor(max_workers=2) as pool:
for second in lists:
all_task.append(pool.submit(action, second)) result=[i.result() for i in all_task]
print(f"result:{result}")
4
5
2
3
result:[4, 5, 2, 3]

等待所有子线程完成

在需要返回值的场景下,主线程需要等到所有子线程返回再进行下一步,阻塞在当前。比如下载图片统一保存,这时就需要在主线程中一直等待,使用wait方法完成。

wait(fs, timeout=None, return_when=ALL_COMPLETED)

wait 接受三个参数:

fs: 表示需要执行的序列

timeout: 等待的最大时间,如果超过这个时间即使线程未执行完成也将返回

return_when:表示wait返回结果的条件,默认为 ALL_COMPLETED 全部执行完成再返回,可选 FIRST_COMPLETED

import time
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED,FIRST_COMPLETED, as_completed lists=[4,5,2,3]
all_task = []
with ThreadPoolExecutor(max_workers=2) as pool:
for second in lists:
all_task.append(pool.submit(action, second)) # 主线程等待所有子线程完成
wait(all_task, return_when=ALL_COMPLETED)
print("----complete-----")
4
5
2
3
----complete-----

等待第一个子线程完成

wait 方法可以设置等待第一个子线程返回就继续执行,表现为主线程在第一个线程返回后便不会阻塞,继续执行下面的操作。

import time
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED,FIRST_COMPLETED, as_completed def action(second):
print(second)
time.sleep(second)
return second lists=[4,5,2,3]
all_task = []
with ThreadPoolExecutor(max_workers=2) as pool:
for second in lists:
all_task.append(pool.submit(action, second)) # 主线程等待第一个子线程完成
wait(all_task, return_when=FIRST_COMPLETED)
print("----complete-----")
4
5
2
----complete-----
3

因为result方法是阻塞的,所以流程会在result这里阻塞直到所有子线程返回,相当于 ALL_COMPLETED 方法。

import time
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED,FIRST_COMPLETED, as_completed def action(second):
print(second)
time.sleep(second)
return second lists=[4,5,2,3]
all_task = []
with ThreadPoolExecutor(max_workers=2) as pool:
for second in lists:
all_task.append(pool.submit(action, second)) # 主线程等待第一个子线程完成
wait(all_task, return_when=FIRST_COMPLETED)
print("----first complete-----") result=[i.result() for i in all_task]
print(f"result:{result}")
print("----complete-----")
4
5
2
----first complete-----
3
result:[4, 5, 2, 3]
----complete-----

返回及时处理

如果不需要等待所有线程全部返回,而是每返回一个子线程就立刻处理,那么就可以使用as_completed获取每一个线程的返回结果。

as_completed() 方法是一个生成器,在没有任务完成的时候,会一直阻塞。当有某个任务完成的时候,会 yield 这个任务,就能执行 for 循环下面的语句,然后继续阻塞住,循环到所有的任务结束。同时,先完成的任务会先返回给主线程。

import time
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED,FIRST_COMPLETED, as_completed def action(second):
print(second)
time.sleep(second)
return second lists=[4,5,2,3]
all_task = []
with ThreadPoolExecutor(max_workers=2) as pool:
for second in lists:
all_task.append(pool.submit(action, second)) for future in as_completed(all_task):
print(f"{future.result()} 返回") print("----complete-----")
4
5
2
4 返回
3
5 返回
2 返回
3 返回
----complete-----

map

map 方法是对序列中每一个元素都执行 action 方法,主要有两个特点:

  1. 不需要将任务submit到线程池
  2. 返回结果的顺序和元素的顺序相同,即使子线程先返回也不会获取结果
map(fn, *iterables, timeout=None)

fn: 第一个参数 fn 是需要线程执行的函数;

iterables:第二个参数接受一个可迭代对象;

timeout: 第三个参数 timeout 跟 wait() 的 timeout 一样,但由于 map 是返回线程执行的结果,如果 timeout小于线程执行时间会抛异常 TimeoutError。

import time
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED,FIRST_COMPLETED, as_completed def action(second):
print(second)
time.sleep(second)
return second lists=[5,1,2,3]
with ThreadPoolExecutor(max_workers=2) as pool:
for result in pool.map(action, lists):
print(f"{result} 返回")
5
1
2
3
5 返回
1 返回
2 返回
3 返回

可以看出返回结果和列表的结果一致,即使第2个元素只需要1s就能返回,也还是等待第一个5s线程返回只有才有结果。

python 线程池 ThreadPoolExecutor的更多相关文章

  1. python线程池ThreadPoolExecutor(上)(38)

    在前面的文章中我们已经介绍了很多关于python线程相关的知识点,比如 线程互斥锁Lock / 线程事件Event / 线程条件变量Condition 等等,而今天给大家讲解的是 线程池ThreadP ...

  2. python线程池ThreadPoolExecutor与进程池ProcessPoolExecutor

    python中ThreadPoolExecutor(线程池)与ProcessPoolExecutor(进程池)都是concurrent.futures模块下的,主线程(或进程)中可以获取某一个线程(进 ...

  3. python线程池ThreadPoolExecutor用法

    线程池concurrent.futures.ThreadPoolExecutor模板 import time from concurrent.futures import ThreadPoolExec ...

  4. python线程池 ThreadPoolExecutor 的用法及实战

    写在前面的话 (https://jq.qq.com/?_wv=1027&k=rX9CWKg4) 文章来源于互联网从Python3.2开始,标准库为我们提供了 concurrent.future ...

  5. Python线程池ThreadPoolExecutor源码分析

    在学习concurrent库时遇到了一些问题,后来搞清楚了,这里记录一下 先看个例子: import time from concurrent.futures import ThreadPoolExe ...

  6. Python 线程池(小节)

    Python 线程池(小节) from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import os,time, ...

  7. python线程池示例

    使用with方式创建线程池,任务执行完毕之后,会自动关闭资源 , 否则就需要手动关闭线程池资源  import threading, time from concurrent.futures impo ...

  8. Python线程池与进程池

    Python线程池与进程池 前言 前面我们已经将线程并发编程与进程并行编程全部摸了个透,其实我第一次学习他们的时候感觉非常困难甚至是吃力.因为概念实在是太多了,各种锁,数据共享同步,各种方法等等让人十 ...

  9. java线程池ThreadPoolExecutor使用简介

    一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...

  10. 线程池ThreadPoolExecutor

    线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int maxi ...

随机推荐

  1. Linux MIPI 摄像头驱动框架编写(RN6752解码芯片)

    一.概述 在编写 MIPI 摄像头驱动之前,需要先了解 Media 子系统的链路关系,这里我就不介绍了,需要的看我之前的笔记:Linux Media 子系统链路分析. 理解 Media 子系统链路关系 ...

  2. Qt源码解析——元对象系统热身

    关键词:Qt 源码 QObject QMetaObject 元对象系统 属性 事件 信号 槽 概述 原系列文章地址 官方文档第二章内容就是元对象系统,它在介绍里描述到: Qt的元对象系统提供了信号和槽 ...

  3. 27. 干货系列从零用Rust编写正反向代理,Rust中日志库的应用基础准备

    wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现websocket代理等,会将实现 ...

  4. bool数据类型用法

    1 来自百度 1.bool为布尔型用作逻辑判断 2 2.bool只有一个字节 3 3.bool取值false和true,0为false,非0为true.(例如-1和2都是true). 4 4.bool ...

  5. 2023-11-18:用go语言,如果一个正方形矩阵上下对称并且左右对称,对称的意思是互为镜像, 那么称这个正方形矩阵叫做神奇矩阵。 比如 : 1 5 5 1 6 3 3 6 6 3 3 6 1 5

    2023-11-18:用go语言,如果一个正方形矩阵上下对称并且左右对称,对称的意思是互为镜像, 那么称这个正方形矩阵叫做神奇矩阵. 比如 : 1 5 5 1 6 3 3 6 6 3 3 6 1 5 ...

  6. H.264中的帧

    导言 高级视频编码 (AVC) 也称为 H.264,是使用最广泛的视频压缩标准.它与所有主要的流式传输协议和容器格式兼容. 当我们使用播放器播放一个视频时,通常会经过:解协议,解封装,音视频解码,音视 ...

  7. 趋势指标(一)MACD指标

    MACD称为异同移动平均线,是从双指数移动平均线发展而来的,由快的指数移动平均线(EMA12)减去慢的指数移动平均线(EMA26)得到快线DIF,再用2×(快线DIF-DIF的9日加权移动均线DEA) ...

  8. vue禁止浏览器F5进行刷新和监听浏览器刷新事件

    项目中有个这样的需求: 进入视频播放页后,添加一个标识,为了防止用户一次播放多个视频,当离开该页面后,如果是从当前正在播放的视频页面离开的,则离开播放页时清除标识,如果是不是则不清除,并且禁止用户按F ...

  9. 洛谷5789 [TJOI2017]可乐(矩阵快速幂,Floyd思想)

    题意:可乐机器人有三种行为: 停在原地,去下一个相邻的城市,自爆.它每一秒都会随机触发一种行为.现在给加里敦星球城市图,在第 0秒时可乐机器人在 1号城市,问经过了 t秒,可乐机器人的行为方案数是多少 ...

  10. 探索 Web API:SpeechSynthesis 与文本语言转换技术

    一.引言 随着科技的不断发展,人机交互的方式也在不断演变.语音识别和合成技术在人工智能领域中具有重要地位,它们为残障人士和日常生活中的各种场景提供了便利.Web API 是 Web 应用程序接口的一种 ...