Python线程池模块ThreadPoolExecutor用法分析

Python线程池模块ThreadPoolExecutor用法分析

对于需要执行大量I/O型任务,使用多线程可以有效提高程序性能的同时,也存在着线程创建与销毁所带来的额外开销、资源竞争和同步问题等问题。线程池技术可以有效地缓解这些问题。Python中线程池的实现有很多,其中“ThreadPoolExecutor”是Python3内置的线程池实现,本文将详细讲解其使用方法。

ThreadPoolExecutor常用方法

创建线程池

ThreadPoolExecutor的构造函数定义为:

ThreadPoolExecutor(max_workers=None, thread_name_prefix="", initializer=None, initargs=())

其中,max_workers限制线程池中该同时运行的线程数量。如果没有设置,线程池默认的线程数量为1个。如果max_workers为None或者为负数,将抛出ValueError异常。thread_name_prefix是一个可选的前缀字符串,用来区分不同线程池的线程名称。initializer是可选的一个回调函数,用来在每个工作线程中启动的一个可调用对象。initargs是initializer回调函数的可变参数。

例如创建一个具有5个线程的线程池:

from concurrent.futures import ThreadPoolExecutor
pool = ThreadPoolExecutor(max_workers=5)

提交任务到线程池

使用ThreadPoolExecutor.submit()方法将一个任务提交给线程池。该方法返回一个Future对象,其中可以通过result()等方法获取任务执行结果。

def func(arg1, arg2):
    # 执行任务
    pass

future = pool.submit(func, arg1, arg2)
result = future.result()

关闭线程池

当线程池不需要再执行新的任务时,应该关闭线程池,以释放所有线程并回收系统资源。可以通过ThreadPoolExecutor.shutdown()或ThreadPoolExecutor.shutdown(wait=True)方法来关闭线程池。

  • ThreadPoolExecutor.shutdown()会禁止提交新的任务,等待所有线程执行完当前任务后关闭线程池。
  • ThreadPoolExecutor.shutdown(wait=True)会禁止提交新的任务,并等待所有线程执行完当前任务后关闭线程池。参数wait接受一个布尔值,用来决定关闭线程池时是否等待所有线程执行完当前任务。

例如:

pool.shutdown(wait=True)

示例一:使用线程池处理I/O型任务

首先,我们定义一个模拟的I/O型任务:

import time

def io_task(task_id):
    print("task %d start" % (task_id))
    time.sleep(1)
    print("task %d end" % (task_id))
    return task_id

然后,我们创建线程池并提交任务:

pool = ThreadPoolExecutor(max_workers=5)
task_results = []
for i in range(10):
    future = pool.submit(io_task, i)
    task_results.append(future)

pool.shutdown(wait=True)

for task_result in task_results:
    print("task %d return %d" % (task_result.result(), task_result.done()))

上述程序开启了一个具有5个线程的线程池,然后循环提交了10个任务到线程池中。由于线程池中一次只能执行一定数量的线程,所以只会同时执行5个任务,其余任务将被放入等待队列中。线程池将逐个执行等待队列中的任务。

示例二:使用线程池处理CPU密集型任务

不过,对于一般的CPU密集型任务,使用多线程反而可能会降低程序效率,因此Python中多线程通常用于处理I/O型任务。为了验证这一点,我们定义一个模拟的CPU密集型任务:

def cpu_task(task_id):
    a = 0
    for i in range(1, 5000001):
        a += i
    print("task %d end" % (task_id))
    return task_id

然后,我们在主线程中依次调用该函数:

start_time = time.time()
for i in range(3):
    cpu_task(i)
end_time = time.time()
print("time-consuming:%.2f s" % (end_time - start_time))

CPU密集型任务在一个线程中依次执行,总共花费了约18秒的时间。接下来,我们将该任务交给一个具有5个线程的线程池:

pool = ThreadPoolExecutor(max_workers=5)
task_results = []
start_time = time.time()
for i in range(3):
    future = pool.submit(cpu_task, i)
    task_results.append(future)

pool.shutdown(wait=True)

for task_result in task_results:
    print("task %d return %d" % (task_result.result(), task_result.done()))
end_time = time.time()
print("time-consuming:%.2f s" % (end_time - start_time))

由于线程池中一次只能执行一定数量的线程,所以只会同时执行5个任务,其余任务将被放入等待队列中。线程池将逐个执行等待队列中的任务。实验结果表明,该程序花费的时间与在一个线程中依次执行的时间基本相同。如果计算时间非常短,线程池的开销可能会反而增大。因此,在执行CPU密集型任务时,尽量不要使用多线程。

总结

通过本文的介绍,可以看出ThreadPoolExecutor提供了比较良好的线程池实现,通过较为简单的调用方式,可以方便地实现多线程,并且有效地缓解了多线程带来的额外开销、资源竞争和同步问题等问题。本文还展示了不同类型任务的实现方式,以示其使用方法和效果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python线程池模块ThreadPoolExecutor用法分析 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • 浅谈云计算之SAN扩展系统设计

    设计背景:不管是公有云还是私有云,为了提供服务的持续性(Business Continuity,BC)和数据的灾难恢复(Disaster Recovery,DR)都不可能只有一个数据中心(Data Center ,DC)。问题 是采用多个DC站点后,每个站点DC的数据要同步,以及为终端用户传输数据提供负载均衡,这些跨城域或广域的DC间该怎样进行数据复制和组织…

    云计算 2023年4月13日
    00
  • 为什么新的5G标准将为技术栈带来更低的 TCO

    ​ 摘要 新5G标准和边缘计算对低延迟的要求,给那些试图将一堆不同组件组装成一个不会出现故障且仍具有低延迟的高成本效益应用程序公司带来了严峻的挑战。事实上,这个问题非常严重,以至于需要重新考虑架构。 想要真正从5G和高速数据带来的发展中获利,需要将多个数据层整合到一个集成堆栈中。 介绍 5G和边缘计算都有改变世界的潜力。事实上,很多人会争辩说,边缘计算已经改…

    2023年4月9日
    00
  • 软件工程与UML—–云班课经验计算

    博客班级 https://edu.cnblogs.com/campus/fzzcxy/2018SE1 作业要求 https://edu.cnblogs.com/campus/fzzcxy/2018SE1/homework/11110 作业目标 编写程序完成云班课成绩计算 作业源代码 https://gitee.com/xie-qiqin/personal 学…

    云计算 2023年4月10日
    00
  • 老公入职第一天:就被同事问了云计算的 三种模式

    目录 目录 一、IaaS(Infrastructure as a Service)基础设施即服务 二、PaaS(Platform as a Service)平台即服务 三、SaaS(Software as a Service)软件即服务 四、三者之间的关联 五、IaaS 和 PaaS 之间的比较 “云”是互联网的一个隐喻,“云计算”其实就是使用互联网来接入存…

    云计算 2023年4月11日
    00
  • 如何利用js给自己照相并修图

    如何利用js给自己照相并修图 在Web开发中,我们可以使用JavaScript来实现照相和修图的功能。本文将提供一个完整攻略,包括如何使用JavaScript来照相和修图,并提供两个示例说明。 步骤1:使用WebRTC API照相 WebRTC API是一个浏览器原生的API,可以访问摄像头和麦克风。以下是使用WebRTC API照相的步骤: 在HTML文件…

    云计算 2023年5月16日
    00
  • 致力于打造下一代去中心化云计算底层操作系统的BHP, 企图打破算力垄断

    云计算作为一种把许多计算资源集合起来,通过软件实现自动化管理,让计算能力如同水电一样让所有人简单取用的商业模式,有效降低了许多中小企业、初创公司的运营成本,不再需要建立自己的机房,同时也为 AWS、Google Cloud、阿里云等巨头带来了丰厚的利润。 但云计算不断发展的同时也带来了算力垄断的问题,一方面,全球网络数据指数型增长,对算力的需求与日俱增,另一…

    云计算 2023年4月13日
    00
  • Hyperpay钱包靠谱吗?Hyperpay究竟怎么样?

    Hyperpay钱包是一款基于区块链技术的安全稳定的数字货币钱包,主要支持比特币、以太坊、EOS等主流数字货币的存储、交易和管理。Hyperpay的安全性较高,拥有多重账户验证、离线钱包、极高的用户隐私及加密技术等特点,可以为数字货币用户提供更加安全、便捷的数字货币使用体验。 Hyperpay钱包的优点 安全稳定 Hyperpay钱包采用多重签名、多重验证等…

    云计算 2023年5月17日
    00
  • 开源:云寻觅中文分词 (Yunxunmi Chinese Word Segmentation) ,词汇440万,10万字文章分词并计算频率不超过1秒

    开源:云寻觅中文分词 (Yunxunmi Chinese Word Segmentation) ,词汇440万,10万字文章分词并计算频率不超过1秒 云寻觅中文分词 (Yunxunmi Chinese Word Segmentation) 指的是将一个汉字序列切成一个一个单独的词。云寻觅中文分词就是将连续的字序列按照一定的规范重新组合成词序列的 过程。中文分…

    2023年4月10日
    00
合作推广
合作推广
分享本页
返回顶部