当前位置:首页 > 科技  > 软件

如何通过Python线程池实现异步编程?

来源: 责编: 时间:2023-08-05 11:45:38 2920观看
导读线程池的概念和基本原理线程池是一种并发处理机制,它可以在程序启动时创建一组线程,并将它们置于等待任务的状态。当任务到达时,线程池中的某个线程会被唤醒并执行任务,执行完任务后线程会返回线程池,等待下一个任务的到来

4ve28资讯网——每日最新资讯28at.com

线程池的概念和基本原理

线程池是一种并发处理机制,它可以在程序启动时创建一组线程,并将它们置于等待任务的状态。当任务到达时,线程池中的某个线程会被唤醒并执行任务,执行完任务后线程会返回线程池,等待下一个任务的到来。这种机制可以减少线程的创建和销毁,提高程序的性能和效率。4ve28资讯网——每日最新资讯28at.com

线程池的基本原理是将任务和线程分离,将任务提交给线程池,由线程池来管理和执行任务。线程池中的线程可以被重复利用,减少了创建和销毁线程的开销,提高了程序的性能和效率。4ve28资讯网——每日最新资讯28at.com

Python 中线程池的实现方式

在 Python 中,线程池可以通过 concurrent.futures 模块中的 ThreadPoolExecutor 类来实现。这个类提供了一些方法来创建和管理线程池,以及提交和执行任务。4ve28资讯网——每日最新资讯28at.com

一、Python线程池的创建和销毁

创建线程池

在 Python 中,可以使用 concurrent.futures 模块中的 ThreadPoolExecutor 类来创建线程池。ThreadPoolExecutor 类的构造函数可以接受一个参数 max_workers,用于指定线程池的大小。如果不指定 max_workers,则线程池的大小会根据 CPU 的核心数来自动确定。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task():    print('Task executed')if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)

在上述代码中,创建了一个包含三个线程的线程池,并提交了一个任务。使用 with 语句可以自动关闭线程池,确保资源的正确释放。4ve28资讯网——每日最新资讯28at.com

销毁线程池

要销毁线程池,可以调用 shutdown() 方法。该方法会等待所有任务执行完毕后再关闭线程池。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task():    print('Task executed')if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)    executor.shutdown()

在上述代码中,关闭了线程池。4ve28资讯网——每日最新资讯28at.com

如果要立即关闭线程池,可以调用 shutdown(wait=False) 方法。该方法会立即关闭线程池,未完成的任务会被取消。这种方式需要特别小心,因为未完成的任务可能会导致程序的异常退出或数据丢失。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task():    print('Task executed')if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)    executor.shutdown(wait=False)

在上述代码中,立即关闭了线程池。4ve28资讯网——每日最新资讯28at.com

线程池的生命周期

线程池的生命周期包括三个阶段:4ve28资讯网——每日最新资讯28at.com

  • 创建阶段:创建线程池,并初始化线程池中的线程。
  • 执行阶段:接收任务并执行任务,直到所有任务执行完毕或线程池被关闭。
  • 销毁阶段:关闭线程池,释放所有资源。

在执行阶段中,无论是任务执行成功还是失败,都需要将线程返回线程池,以便线程池继续利用。如果任务执行失败,可以使用 Future 对象的 exception() 方法获取异常信息。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task():    print('Task executed')    raise Exception('Task failed')if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)        try:            result = future.result()        except Exception as e:            print(f'Task failed: {e}')

在上述代码中,提交了一个会抛出异常的任务,并使用 try...except 语句来捕获异常信息。4ve28资讯网——每日最新资讯28at.com

在销毁阶段中,需要确保所有任务执行完毕后再关闭线程池。如果直接关闭线程池,未完成的任务可能会导致程序的异常退出或数据丢失。4ve28资讯网——每日最新资讯28at.com

线程池的异常处理

在使用线程池时,可能会出现各种异常,例如任务执行失败、线程池关闭失败等。为了保证程序的健壮性和可靠性,需要对这些异常进行处理。4ve28资讯网——每日最新资讯28at.com

在任务执行失败时,可以使用 Future 对象的 exception() 方法获取异常信息。在线程池关闭失败时,可以使用 ThreadPoolExecutor 类的 shutdown() 方法的返回值来判断是否成功关闭线程池。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task():    print('Task executed')    raise Exception('Task failed')if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)        try:            result = future.result()        except Exception as e:            print(f'Task failed: {e}')        success = executor.shutdown(wait=False)        if not success:            print('Failed to shutdown thread pool')

在上述代码中,提交了一个会抛出异常的任务,并使用 try...except 语句来捕获异常信息。在关闭线程池时,使用 wait=False 参数来立即关闭线程池,并使用 shutdown() 方法的返回值来判断是否成功关闭线程池。4ve28资讯网——每日最新资讯28at.com

二、Python线程池的任务提交和执行

提交任务到线程池

要提交任务到线程池中,可以使用 submit() 方法,该方法会返回一个 Future 对象,表示任务的执行结果。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task():    print('Task executed')    return 'Task result'if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)        print(future.result())

在上述代码中,提交了一个任务,并使用 future.result() 方法获取任务的执行结果。4ve28资讯网——每日最新资讯28at.com

可以使用 map() 方法来批量提交任务,并获得所有任务的执行结果。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task(i):    print(f'Task {i} executed')    return f'Task {i} result'if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        results = executor.map(task, range(5))        for result in results:            print(result)

在上述代码中,使用 map() 方法批量提交任务,并获得所有任务的执行结果。4ve28资讯网——每日最新资讯28at.com

控制任务的执行顺序

在默认情况下,线程池会根据任务的提交顺序来执行任务。但是,如果需要控制任务的执行顺序,可以使用 submit() 方法的返回值 Future 对象来控制任务的执行。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task(i):    print(f'Task {i} executed')    return f'Task {i} result'if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        futures = [executor.submit(task, i) for i in range(5)]        for future in concurrent.futures.as_completed(futures):            result = future.result()            print(result)

在上述代码中,使用 submit() 方法提交了多个任务,并将返回值 Future 对象保存在列表中。使用
concurrent.futures.as_completed() 函数来获取任务的执行结果,并按照完成顺序输出结果。
4ve28资讯网——每日最新资讯28at.com

还可以使用 future.add_done_callback() 方法来注册回调函数,当任务执行完毕时自动调用回调函数。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task(i):    print(f'Task {i} executed')    return f'Task {i} result'def callback(future):    result = future.result()    print(result)if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        futures = [executor.submit(task, i) for i in range(5)]        for future in futures:            future.add_done_callback(callback)

在上述代码中,使用 submit() 方法提交了多个任务,并使用 future.add_done_callback() 方法注册回调函数。当任务执行完毕时,会自动调用回调函数。4ve28资讯网——每日最新资讯28at.com

取消任务的执行

在使用线程池时,可能需要取消正在执行的任务。可以使用 Future 对象的 cancel() 方法来取消任务的执行。如果任务已经执行完毕或无法取消,cancel() 方法会返回 False。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresimport timedef task():    print('Task started')    time.sleep(5)    print('Task finished')    return 'Task result'if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)        time.sleep(2)        canceled = future.cancel()        if canceled:            print('Task canceled')        else:            print('Task not canceled')

在上述代码中,提交一个任务并等待 2 秒后取消任务的执行。如果任务已经执行完毕或无法取消,cancel() 方法会返回 False。4ve28资讯网——每日最新资讯28at.com

等待所有任务执行完毕

在使用线程池时,可能需要等待所有任务执行完毕。可以使用 wait() 方法来等待所有任务执行完毕。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task(i):    print(f'Task {i} executed')    return f'Task {i} result'if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        futures = [executor.submit(task, i) for i in range(5)]        concurrent.futures.wait(futures)        for future in futures:            result = future.result()            print(result)

在上述代码中,使用 submit() 方法提交了多个任务,并将返回值 Future 对象保存在列表中。使用 concurrent.futures.wait() 函数来等待所有任务执行完毕。4ve28资讯网——每日最新资讯28at.com

三、Python线程池的参数和配置

下面是对 Python 中线程池的参数和配置的深入讲解。4ve28资讯网——每日最新资讯28at.com

线程池的大小

线程池的大小决定了可以同时执行的任务数。在 Python 中,可以使用 max_workers 参数来配置线程池的大小。如果不指定 max_workers,线程池的大小会根据 CPU 的核心数来自动确定。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task():    print('Task executed')if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)

在上述代码中,创建了一个包含三个线程的线程池。如果需要更改线程池的大小,只需修改 max_workers 的值即可。4ve28资讯网——每日最新资讯28at.com

线程池的超时设置

在 Python 中,可以使用 timeout 参数来设置任务的执行超时时间。如果任务在指定的时间内没有执行完毕,线程池会自动取消任务的执行,并抛出 concurrent.futures.TimeoutError 异常。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresimport timedef task():    print('Task started')    time.sleep(5)    print('Task finished')    return 'Task result'if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:        future = executor.submit(task)        try:            result = future.result(timeout=2)            print(result)        except concurrent.futures.TimeoutError:            print('Task timeout')

在上述代码中,提交了一个需要 5 秒才能执行完毕的任务,并设置超时时间为 2 秒。因为任务没有在指定时间内执行完毕,所以会抛出 concurrent.futures.TimeoutError 异常。4ve28资讯网——每日最新资讯28at.com

线程池的任务队列

在线程池中,如果所有线程都正在执行任务,新的任务会被加入到任务队列中等待执行。在 Python 中,可以使用 queue_size 参数来配置任务队列的大小。如果任务队列已满,新的任务会被拒绝执行,并抛出 concurrent.futures.ThreadPoolExecutor 异常。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresdef task():    print('Task executed')if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3, queue_size=2) as executor:        for i in range(5):            future = executor.submit(task)

在上述代码中,创建了一个包含三个线程和大小为 2 的任务队列的线程池。提交了 5 个任务,其中前两个任务会被立即执行,后三个任务会被加入到任务队列中等待执行。因为任务队列只能容纳 2 个任务,所以第四个任务会被拒绝执行,并抛出 concurrent.futures.ThreadPoolExecutor 异常。4ve28资讯网——每日最新资讯28at.com

线程池的线程名称和优先级

在线程池中,可以为每个线程设置名称和优先级。在 Python 中,可以使用 thread_name_prefix 和 thread_priority 参数来配置线程名称和优先级。4ve28资讯网——每日最新资讯28at.com

import concurrent.futuresimport threadingdef task():    print(f'Task executed by {threading.current_thread().name}')if __name__ == '__main__':    with concurrent.futures.ThreadPoolExecutor(max_workers=3, thread_name_prefix='MyThread-', thread_priority=1) as executor:        future = executor.submit(task)

在上述代码中,创建了一个包含三个线程的线程池,并为每个线程设置名称前缀为 MyThread-,优先级为 1。提交了一个任务,任务会被其中一个线程执行,并在执行时输出线程的名称。4ve28资讯网——每日最新资讯28at.com

四、线程池的应用场景

线程池适用于需要并发执行多个任务的场景,例如:4ve28资讯网——每日最新资讯28at.com

  • 网络爬虫:同时爬取多个网页。
  • 数据库操作:同时查询多个数据表。
  • 图像处理:同时处理多张图片。
  • 并发编程:同时执行多个线程。

使用线程池可以减少线程的创建和销毁,提高程序的性能和效率,同时还可以控制线程池的大小和任务的执行顺序。4ve28资讯网——每日最新资讯28at.com

总之,线程池是一个非常有用的并发处理机制,可以提高程序的性能和效率,同时也需要仔细设计和实现,以避免并发问题和线程安全问题。4ve28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-124-0.html如何通过Python线程池实现异步编程?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 之家push系统迭代之路

下一篇: 三言两语说透柯里化和反柯里化

标签:
  • 热门焦点
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • 分布式系统中的CAP理论,面试必问,你理解了嘛?

    分布式系统中的CAP理论,面试必问,你理解了嘛?

    对于刚刚接触分布式系统的小伙伴们来说,一提起分布式系统,就感觉高大上,深不可测。而且看了很多书和视频还是一脸懵逼。这篇文章主要使用大白话的方式,带你理解一下分布式系统
  • 如何使用JavaScript创建一只图像放大镜?

    如何使用JavaScript创建一只图像放大镜?

    译者 | 布加迪审校 | 重楼如果您曾经浏览过购物网站,可能遇到过图像放大功能。它可以让您放大图像的特定区域,以便浏览。结合这个小小的重要功能可以大大改善您网站的用户体验
  • 本地生活这块肥肉,拼多多也想吃一口

    本地生活这块肥肉,拼多多也想吃一口

    出品/壹览商业 作者/李彦编辑/木鱼拼多多也看上本地生活这块蛋糕了。近期,拼多多在App首页“充值中心”入口上线了本机生活界面。壹览商业发现,该界面目前主要
  • 自律,给不了Keep自由!

    自律,给不了Keep自由!

    来源 | 互联网品牌官作者 | 李大为编排 | 又耳 审核 | 谷晓辉自律能不能给用户自由暂时不好说,但大概率不能给Keep自由。近日,全球最大的在线健身平台Keep正式登陆港交所,努力
  • 造车两年股价跌六成,小米的估值逻辑变了吗?

    造车两年股价跌六成,小米的估值逻辑变了吗?

    如果从小米官宣造车后的首个交易日起持有小米集团的股票,那么截至2023年上半年最后一个交易日,投资者将浮亏59.16%,同区间的恒生科技指数跌幅为52.78%
  • 7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
  • 机构称Q2全球智能手机出货量同比下滑11% 苹果份额依旧第2

    机构称Q2全球智能手机出货量同比下滑11% 苹果份额依旧第2

    7月20日消息,据外媒报道,研究机构的报告显示,由于需求下滑,今年二季度全球智能手机的出货量,同比下滑了11%,三星、苹果等主要厂商的销量,较去年同期均有下
  • 苹果140W USB-C充电器:采用氮化镓技术

    苹果140W USB-C充电器:采用氮化镓技术

    据10 月 30 日 9to5 Mac 消息报道,当苹果推出新的 MacBook Pro 2021 时,该公司还推出了新的 140W USB-C 充电器,附赠在 MacBook Pro 16 英寸机型的盒子里,也支
Top