广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python并发编程之线程池/进程池
  • 727
分享到

Python并发编程之线程池/进程池

2023-06-02 08:06:17 727人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

原文来自开源中国前言python标准库提供线程和多处理模块来编写相应的多线程/多进程代码,但当项目达到一定规模时,频繁地创建/销毁进程或线程是非常消耗资源的,此时我们必须编写自己的线程池/进程池来交换时间空间。但是从python3.2开始,

原文来自开源中国

前言

python标准库提供线程和多处理模块来编写相应的多线程/多进程代码,但当项目达到一定规模时,频繁地创建/销毁进程或线程是非常消耗资源的,此时我们必须编写自己的线程池/进程池来交换时间空间。但是从python3.2开始,标准库为我们提供了并发的。Futures模块,它提供两个类:ThreadPool Executor和ProcessPool Executor。它实现线程和多处理的进一步抽象,并为编写线程池/进程池提供直接支持。

Executor和Future

concurrent.futures模块的基础是Exectuor,Executor是一个抽象类,它不能被直接使用。但是它提供的两个子类ThreadPoolExecutor和ProcessPoolExecutor却是非常有用,顾名思义两者分别被用来创建线程池和进程池的代码。我们可以将相应的tasks直接放入线程池/进程池,不需要维护Queue来操心死的问题,线程池/进程池会自动帮我们调度。

使用submit来操作线程池/进程池

我们先通过下面这段代码来了解一下线程池的概念

# example1.pyfrom concurrent.futures import ThreadPoolExecutorimport timedef return_future_result(message):    time.sleep(2)    return messagepool = ThreadPoolExecutor(max_workers=2)  # 创建一个最大可容纳2个task的线程池future1 = pool.submit(return_future_result, ("hello"))  # 往线程池里面加入一个taskfuture2 = pool.submit(return_future_result, ("world"))  # 往线程池里面加入一个taskprint(future1.done())  # 判断task1是否结束time.sleep(3)print(future2.done())  # 判断task2是否结束print(future1.result())  # 查看task1返回的结果print(future2.result())  # 查看task2返回的结果

让我们根据操作结果进行分析。我们使用submit方法将任务添加到线程池,submit返回一个将来的对象,这可以简单地理解为将来要完成的操作。在第一份印刷声明中,很明显我们的未来1由于时间的原因没有完成。睡眠(2),因为我们使用时间挂起了主线程。sleep(3),所以到第二个print语句时,线程池中的所有任务都已完成。

ziwenxie :: ~ » Python example1.pyFalseTruehelloworld# 在上述程序执行的过程中,通过ps命令我们可以看到三个线程同时在后台运行ziwenxie :: ~ » ps -eLf | grep pythonziwenxie      8361  7557  8361  3    3 19:45 pts/0    00:00:00 python example1.pyziwenxie      8361  7557  8362  0    3 19:45 pts/0    00:00:00 python example1.pyziwenxie      8361  7557  8363  0    3 19:45 pts/0    00:00:00 python example1.py

上面的代码我们也可以改写为进程池形式,api和线程池如出一辙,我就不罗嗦了。

# example2.pyfrom concurrent.futures import ProcessPoolExecutorimport timedef return_future_result(message):    time.sleep(2)    return messagepool = ProcessPoolExecutor(max_workers=2)future1 = pool.submit(return_future_result, ("hello"))future2 = pool.submit(return_future_result, ("world"))print(future1.done())time.sleep(3)print(future2.done())print(future1.result())print(future2.result())

下面是运行结果

ziwenxie :: ~ » python example2.pyFalseTruehelloworldziwenxie :: ~ » ps -eLf | grep pythonziwenxie      8560  7557  8560  3    3 19:53 pts/0    00:00:00 python example2.pyziwenxie      8560  7557  8563  0    3 19:53 pts/0    00:00:00 python example2.pyziwenxie      8560  7557  8564  0    3 19:53 pts/0    00:00:00 python example2.pyziwenxie      8561  8560  8561  0    1 19:53 pts/0    00:00:00 python example2.pyziwenxie      8562  8560  8562  0    1 19:53 pts/0    00:00:00 python example2.py
使用map/wait来操作线程池/进程池

除了submit,Exectuor还为我们提供了map方法,和内建的map用法类似,下面我们通过两个例子来比较一下两者的区别。

使用submit操作回顾

# example3.pyimport concurrent.futuresimport urllib.requestURLS = ['Http://httpbin.org', 'http://example.com/', 'https://api.GitHub.com/']def load_url(url, timeout):    with urllib.request.urlopen(url, timeout=timeout) as conn:        return conn.read()# We can use a with statement to ensure threads are cleaned up promptlywith concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:    # Start the load operations and mark each future with its URL    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}    for future in concurrent.futures.as_completed(future_to_url):        url = future_to_url[future]        try:            data = future.result()        except Exception as exc:            print('%r generated an exception: %s' % (url, exc))        else:            print('%r page is %d bytes' % (url, len(data)))

从运行结果可以看出,as_completed不是按照URLS列表元素的顺序返回的。

ziwenxie :: ~ » python example3.py'http://example.com/' page is 1270 byte'https://api.github.com/' page is 2039 bytes'http://httpbin.org' page is 12150 bytes

使用map

# example4.pyimport concurrent.futuresimport urllib.requestURLS = ['http://httpbin.org', 'http://example.com/', 'https://api.github.com/']def load_url(url):    with urllib.request.urlopen(url, timeout=60) as conn:        return conn.read()# We can use a with statement to ensure threads are cleaned up promptlywith concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:    for url, data in zip(URLS, executor.map(load_url, URLS)):        print('%r page is %d bytes' % (url, len(data)))

从运行结果可以看出,map是按照URLS列表元素的顺序返回的,并且写出的代码更加简洁直观,我们可以根据具体的需求任选一种。

ziwenxie :: ~ » python example4.py'http://httpbin.org' page is 12150 bytes'http://example.com/' page is 1270 bytes'https://api.github.com/' page is 2039 bytes

第三种选择wait

wait方法接会返回一个tuple(元组),tuple中包含两个set(集合),一个是completed(已完成的)另外一个是uncompleted(未完成的)。使用wait方法的一个优势就是获得更大的自由度,它接收三个参数FIRST_COMPLETED, FIRST_EXCEPTION 和ALL_COMPLETE,默认设置为ALL_COMPLETED。

我们通过下面这个例子来看一下三个参数的区别

from concurrent.futures import ThreadPoolExecutor, wait, as_completedfrom time import sleepfrom random import randintdef return_after_random_secs(num):    sleep(randint(1, 5))    return "Return of {}".fORMat(num)pool = ThreadPoolExecutor(5)futures = []for x in range(5):    futures.append(pool.submit(return_after_random_secs, x))print(wait(futures))# print(wait(futures, timeout=None, return_when='FIRST_COMPLETED'))

如果采用默认的ALL_COMPLETED,程序会阻塞直到线程池里面的所有任务都完成。

ziwenxie :: ~ » python example5.pyDoneAndNotDoneFutures(done={<Future at 0x7f0b06c9bc88 state=finished returned str>,<Future at 0x7f0b06cbaa90 state=finished returned str>,<Future at 0x7f0b06373898 state=finished returned str>,<Future at 0x7f0b06352ba8 state=finished returned str>,<Future at 0x7f0b06373b00 state=finished returned str>}, not_done=set())

如果采用FIRST_COMPLETED参数,程序并不会等到线程池里面所有的任务都完成。

ziwenxie :: ~ » python example5.pyDoneAndNotDoneFutures(done={<Future at 0x7f84109edb00 state=finished returned str>,<Future at 0x7f840e2e9320 state=finished returned str>,<Future at 0x7f840f25ccc0 state=finished returned str>},not_done={<Future at 0x7f840e2e9ba8 state=running>,<Future at 0x7f840e2e9940 state=running>})

--结束END--

本文标题: Python并发编程之线程池/进程池

本文链接: https://www.lsjlt.com/news/229543.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python并发编程之线程池/进程池
    原文来自开源中国前言python标准库提供线程和多处理模块来编写相应的多线程/多进程代码,但当项目达到一定规模时,频繁地创建/销毁进程或线程是非常消耗资源的,此时我们必须编写自己的线程池/进程池来交换时间空间。但是从Python3.2开始,...
    99+
    2023-06-02
  • Java并发编程面试之线程池
    目录什么是线程池线程池好处线程池的执行流程怎么用线程池corePoolSizemaximumPoolSizekeepAliveTimeunitworkQueuethreadFacto...
    99+
    2022-11-12
  • Java手写线程池之向JDK线程池进发
    目录前言JDK线程池一瞥自己动手实现线程池线程池参数介绍实现Runnable实现Callable拒绝策略的实现线程池关闭实现工作线程的工作实现线程池实现的BUG完整代码线程池测试总结...
    99+
    2022-11-13
    Java手写线程池 Java线程池
  • Java并发编程之线程池的示例分析
    这篇文章将为大家详细讲解有关Java并发编程之线程池的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。什么是线程池是一种基于池化思想管理线程的工具。池化技术:池化技术简单点来说,就是提前保存大量的资...
    99+
    2023-06-20
  • python中ThreadPoolExecutor线程池和ProcessPoolExecutor进程池
    目录1、ThreadPoolExecutor多线程<1>为什么需要线程池呢<2>标准库concurrent.futures模块<3>简单使用<...
    99+
    2022-11-11
  • Java并发之怎么使用线程池
    这篇文章主要介绍“Java并发之怎么使用线程池”,在日常操作中,相信很多人在Java并发之怎么使用线程池问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java并发之怎么使用线程池”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-16
  • 【Linux网络编程】高并发服务器框架 线程池介绍+线程池封装
    目录 前言 一、线程池介绍 💻线程池基本概念 💻线程池组成部分 💻线程池工作原理  二、线程池代码封装 🌈main.cpp 🌈ThreadPool.h ...
    99+
    2023-10-20
    linux 网络 tcp/ip c++ ubuntu
  • 线程池之newFixedThreadPool定长线程池的实例
    newFixedThreadPool定长线程池的实例 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。newFixedThr...
    99+
    2022-11-12
  • Python之ThreadPoolExecutor线程池问题
    目录概念实例简单使用as_completedmapwait源码分析1.init方法2.submit方法3.adjust_thread_count方法4._WorkItem对象5.线程...
    99+
    2023-03-14
    Python线程池 ThreadPoolExecutor线程池 Python ThreadPoolExecutor
  • python并发编程之多线程编程
    一、threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍 二、开启线程的两种方式 方式一: from threading import ...
    99+
    2023-01-31
    之多 线程 python
  • 进程池、线程池、回调函数、协程
    摘要: 进程池与线程池 同步调用和异步调用 回调函数 协程 一、进程池与线程池: 1、池的概念:   不管是线程还是进程,都不能无限制的开下去,总会消耗和占用资源。   也就是说,硬件的承载能力是有限度的,在保证高效率工作的同时应该还...
    99+
    2023-01-31
    线程 回调 函数
  • 线程池之newCachedThreadPool可缓存线程池的实例
    java线程池: Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,...
    99+
    2022-11-12
  • 解密TaurusDB存储端高并发之线程池
    图1 TaurusDB整体架构 图2 slice功能组件 从图2可知,TaurusDB的存储层,不单单只做存储相关的工作,也需要大量的算力,比如consolidation生成特定数据页、compation回收旧版本数据、Buff...
    99+
    2020-11-07
    解密TaurusDB存储端高并发之线程池
  • C#多线程之线程池(ThreadPool)
    一、简介 前面介绍了平时用到的大多数的多线程的例子,但在实际开发中使用的线程往往是大量的和更为复杂的,这时,每次都创建线程、启动线程。从性能上来讲,这样做并不理想(因为每使用一个线程...
    99+
    2022-11-13
  • 并发编程系列---【线程池七大核心参数】
    一、七大核心参数 corePoolSize                            核心线程数 maximumPoolSize                   最大线程池参数 keepAliveTime       ...
    99+
    2023-09-03
    java jvm 开发语言
  • Python自带的线程池和进程池有什么用
    这篇文章主要介绍“Python自带的线程池和进程池有什么用”,在日常操作中,相信很多人在Python自带的线程池和进程池有什么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”...
    99+
    2022-10-19
  • python中ThreadPoolExecutor线程池和ProcessPoolExecutor进程池怎么使用
    这篇文章主要介绍了python中ThreadPoolExecutor线程池和ProcessPoolExecutor进程池怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇python中ThreadPoolE...
    99+
    2023-07-02
  • 多线程编程(3):线程池ThreadPo
    在面向对象编程中,经常会面对创建对象和销毁对象的情况,如果不正确处理的话,在短时间内创建大量对象然后执行简单处理之后又要销毁这些刚刚建立的对象,这是一个非常消耗性能的低效行为,所以很多面向对象语言中在内部使用对象池来处理这种情况,以提高性能...
    99+
    2023-01-31
    线程 多线程 ThreadPo
  • python 线程池threadpool
    最近在做一个视频设备管理的项目,设备包括(摄像机,DVR,NVR等),包括设备信息补全,设备状态推送,设备流地址推送等,如果同时导入的设备数量较多,如果使用单线程进行设备检测,那么由于设备数量较多,会带来较大的延时,因此考虑多线程处理此问...
    99+
    2023-01-31
    线程 python threadpool
  • python线程池(threadpool
    最近碰到个问题,需要telnet登录上千台机器去取主机名;其中有用户名密码交互部分,有需要延迟的部分,大概一次登录一次到处理完要10s,1000台机器串行处理就需要1000×10s,差不多三个小时,这是很难受的事情; 之前用thread的...
    99+
    2023-01-31
    线程 python threadpool
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作