python 线程池 ThreadPoolExecutor

从Python3.2开始,标准库为我们提供了concurrent.futures 模块,它提供了 ThreadPoolExecutor (线程池)和 ProcessPoolExecutor (进程池)两个类。
相比 threading 等模块,该模块通过 submit 返回的是一个 future 对象,它是一个未来可期的对象,通过它可以获取某一个线程执行的状态或者某一个任务执行的状态及返回值:
- 主线程可以获取某一个线程(或者任务的)的状态,以及返回值。
- 当一个线程完成的时候,主线程能够立即知道。
基础语法介绍
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 方法,主要有两个特点:
- 不需要将任务submit到线程池
- 返回结果的顺序和元素的顺序相同,即使子线程先返回也不会获取结果
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的更多相关文章
- python线程池ThreadPoolExecutor(上)(38)
在前面的文章中我们已经介绍了很多关于python线程相关的知识点,比如 线程互斥锁Lock / 线程事件Event / 线程条件变量Condition 等等,而今天给大家讲解的是 线程池ThreadP ...
- python线程池ThreadPoolExecutor与进程池ProcessPoolExecutor
python中ThreadPoolExecutor(线程池)与ProcessPoolExecutor(进程池)都是concurrent.futures模块下的,主线程(或进程)中可以获取某一个线程(进 ...
- python线程池ThreadPoolExecutor用法
线程池concurrent.futures.ThreadPoolExecutor模板 import time from concurrent.futures import ThreadPoolExec ...
- python线程池 ThreadPoolExecutor 的用法及实战
写在前面的话 (https://jq.qq.com/?_wv=1027&k=rX9CWKg4) 文章来源于互联网从Python3.2开始,标准库为我们提供了 concurrent.future ...
- Python线程池ThreadPoolExecutor源码分析
在学习concurrent库时遇到了一些问题,后来搞清楚了,这里记录一下 先看个例子: import time from concurrent.futures import ThreadPoolExe ...
- Python 线程池(小节)
Python 线程池(小节) from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import os,time, ...
- python线程池示例
使用with方式创建线程池,任务执行完毕之后,会自动关闭资源 , 否则就需要手动关闭线程池资源 import threading, time from concurrent.futures impo ...
- Python线程池与进程池
Python线程池与进程池 前言 前面我们已经将线程并发编程与进程并行编程全部摸了个透,其实我第一次学习他们的时候感觉非常困难甚至是吃力.因为概念实在是太多了,各种锁,数据共享同步,各种方法等等让人十 ...
- java线程池ThreadPoolExecutor使用简介
一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...
- 线程池ThreadPoolExecutor
线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int maxi ...
随机推荐
- 用原型实现Class的各项语法
本人之前对Class一直不够重视.平时对原型的使用,也仅限于在构造函数的prototype上挂属性.原型尚且用不着,更何况你Class只是原型的一颗语法糖? 直到公司开始了一个webgis项目,使用o ...
- window.onload 触发时机问题
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- 机器人的运动范围(dfs)(leetcode 4.8 每日打卡)
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上.下移动一格(不能移动到方格外),也不能进入行坐标和列 ...
- Grid 拖拽布局实现
最近有个需求需要实现自定义首页布局,需要将屏幕按照 6 列 4 行进行等分成多个格子,然后将组件可拖拽对应格子进行渲染展示. 示例 对比一些已有的插件,发现想要实现产品的交互效果,没有现成可用的.本身 ...
- games101-2 透视深度插值矫正与抗锯齿分析
透视深度插值矫正与抗锯齿分析 深度插值的差错原因 透视深度插值公式推导 games101中的错误 msaa与ssaa简要定义 games101中ssaa的实现 games101中msaa的实现 深度插 ...
- HTML5语法总结大全
参考书籍: <HTML与CSS3基础教程> 参考视频: HTML5完整教学通俗易懂 2023新版前端Web开发HTML5+CSS3+移动web视频教程,前端web入门首选黑马程序员 参考网 ...
- hexo+icarus博客搭建
展示效果:米七小站 环境准备 安装nodejs.git.hexo Hexo官网文档 Hexo初始化项目 $ hexo init myblog $ cd myblog $ yarn 查看效果 $ hex ...
- Gradle导致Lombok不生效问题
现象 从debug看是可以查询到数据的,但是返回起前端是没有数据的 解决办法 // 引入lombok注解处理器 annotationProcessor,不然lombok不会生效 annotationP ...
- 云端开炉,线上训练,Bert-vits2-v2.2云端线上训练和推理实践(基于GoogleColab)
假如我们一定要说深度学习入门会有一定的门槛,那么设备成本是一个无法避开的话题.深度学习模型通常需要大量的计算资源来进行训练和推理.较大规模的深度学习模型和复杂的数据集需要更高的计算能力才能进行有效的训 ...
- 在arm架构的银河麒麟系统部署Nginx
以下是在arm架构的银河麒麟系统上部署Nginx的详细步骤: 1. 创建文件夹 首先,在合适的位置创建必要的文件夹.在本例中,我们将创建/opt/nginx和/usr/src/nginx两个文件夹. ...