python 创建和使用线程池

这篇具有很好参考价值的文章主要介绍了python 创建和使用线程池。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

众所周知,python3多线程有threading,很好的支持了多线程,那么问题来了,为什么还需要线程池呢,其实很好回答,如果你要爬取网站有八百页,每页设置一个线程,难道能开启八百个么,光切换的时间也很高了吧。这时候就需要用到线程池,可以设置一个20的线程池,同时只有20个线程在运行,剩下的排队。直接上讲解

线程池模块

在threading中是没有线程池相关功能的,想要运行线程池需要自己重写,很明显像我这么懒不可能重写,而且自己编写线程池很难写的比较完美,还需要考虑复杂情况下的线程同步,很容易发生死锁。所以就用到了这个模块,

from concurrent.futures import ThreadPoolExecutor

从Python3.2开始,标准库为我们提供了concurrent.futures模块,它提供了ThreadPoolExecutor和ProcessPoolExecutor两个类,实现了对threading和multiprocessing的进一步抽象(线程池和进程池的唯一区别就是线程与进程,使用方法,内置函数等都完全一样),可以帮我们自动调度线程,省下大量时间,废话少说,直接上代码:

def thread_text(i,y):
    time.sleep(i+y)
    return i+y
if __name__ == '__main__':
    executor = ThreadPoolExecutor(max_workers=5)
    executor1 = executor.submit(thread_text, 1,1)
    executor2 = executor.submit(thread_text, 2,1)
    executor.shutdown()

首先需要实例化,然后在实例化的同时设置最大线程数,然后使用submit提交线程就ok啦,而且与threading.Thread 的线程不同的是,线程池不阻塞,立即执行,也就是说,不需要start来启动它,

  • 知识点一:线程池不阻塞,不需要start

而且想必有些同学已经看出我这个例子的常规例子的不同了,那就是我传了两个参数,这里也是为了区别threading.Thread的参数,众所周知,threading模块对方法传入参数是以元组的形式,比如我上面写的方法,如果用threading调用的话应该这么写threading.Thread(target=thread_text,args=(1,1)),而线程池则不是,如果翻过源码会发现ThreadPoolExecutor没有固定参数,只有*args和**kwargs,所以,线程池如果要传入多个参数,只需要按照参数位置跟在后面即可。

  • 知识点二:线程池传参不要元组,接着往后写,有多少写多少

在介绍一下它的几个其他函数:
Future 提供了如下方法:

  • cancel():取消该 Future 代表的线程任务。如果该任务正在执行,不可取消,则该方法返回 False;否则,程序会取消该任务,并返回 True。
  • cancelled():返回 Future 代表的线程任务是否被成功取消。
    running():如果该 Future 代表的线程任务正在执行、不可被取消,该方法返回 True。
  • done():如果该 Funture 代表的线程任务被成功取消或执行完成,则该方法返回 True。
  • result(timeout=None):获取该 Future 代表的线程任务最后返回的结果。如果 Future 代表的线程任务还未完成,该方法将会阻塞当前线程,其中 timeout 参数指定最多阻塞多少秒。
  • exception(timeout=None):获取该 Future 代表的线程任务所引发的异常。如果该任务成功完成,没有异常,则该方法返回 None。
  • add_done_callback(fn):为该 Future 代表的线程任务注册一个“回调函数”,当该任务成功完成时,程序会自动触发该 fn 函数。
  • as_completed:上面虽然提供了判断任务是否结束的方法,但是不能在主线程中一直判断啊。有时候我们是得知某个任务结束了,就去获取结果,而不是一直判断每个任务有没有结束。这是就可以使用as_completed方法一次取出所有任务的结果。
from concurrent.futures import ThreadPoolExecutor,as_completed
def thread_text(i,y):
    time.sleep(i+y)
    return i+y
if __name__ == '__main__':
    executor = ThreadPoolExecutor(max_workers=5)
    executor1 = executor.submit(thread_text, 1,1)
    executor2 = executor.submit(thread_text, 2,1)
    for i in as_completed([executor1,executor2]):
        print(i.result())
    executor.shutdown()

as_completed()方法是一个生成器,在没有任务完成的时候,会阻塞,在有某个任务完成的时候,会yield这个任务,就能执行for循环下面的语句,然后继续阻塞住,循环到所有的任务结束。从结果也可以看出,先完成的任务会先通知主线程。

map

除了submit,ThreadPoolExecutor还提供了map函数来添加线程,与常规的map类似,区别在于线程池的 map() 函数会为 iterables 的每个元素启动一个线程,以并发方式来执行 func 函数. 同时,使用map函数,还会自动获取返回值,相当于这样,executor.submit(func).result(),
看例子:

from concurrent.futures import ThreadPoolExecutor,as_completed
def thread_text(i,y):
    time.sleep(i+y)
    return i+y
if __name__ == '__main__':
    executor = ThreadPoolExecutor(max_workers=5)
    li2 = [1,1,1,1,1]
    for i in executor.map(thread_text, range(1, 5), li2):
        print(i)
    print('-------')
    executor.shutdown()

同时,输出顺序和列表的顺序相同,从代码可以看出,使用map函数使得代码更简洁,所以常规使用建议直接使用map。

补充
  1. 不管使用map还是submit,如果子线程发生异常,都会等所有线程执行结束后返回异常,即。线程池以后的代码是不会执行的,因为在线程池结束的瞬间就报错退出了。
  2. map和submit的区别是,submit可以使用exception()方法来捕获异常,使之不会影响到主程序,而map则无法捕获,只能异常退出。submit捕获异常示例如下:
from concurrent.futures import ThreadPoolExecutor,as_completed
def thread_text(i,y):
    time.sleep(i+y)
    return i+y
if __name__ == '__main__':
    executor = ThreadPoolExecutor(max_workers=5)
    executor1 = executor.submit(thread_text, 1,1)
    executor2 = executor.submit(thread_text, 2,1)
    for i in as_completed([executor1,executor2]):
        if i.exception():
            print(i.exception)
        else:
            print(i.result())
    executor.shutdown()

另外,线程锁依然是用threading模块的,线程池这里并没有另外设置锁相关内容。

参考文档
[python] ThreadPoolExecutor线程池
Python线程池及其原理和使用(超级详细)文章来源地址https://www.toymoban.com/news/detail-553196.html

到了这里,关于python 创建和使用线程池的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python创建线程和结束线程

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在 Python 中,线程是一种轻量级的执行单元,允许我们在程序中同时执行多个任务。线程的创建和结束是多线程编程中的核心概念之一。在本

    2024年04月25日
    浏览(36)
  • 【Linux】C语言中多线程的创建、退出、回收、分离

    线程是轻量级的进程(LWP:light weight process),在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。操作系统会以进程为单位,分配系统资源,可以这样理解, 进程是资源分配的最小单位,线程是操

    2024年02月09日
    浏览(42)
  • 第三章 LInux多线程开发 3.1-3.5线程创建 终止 分离

    一般情况下,main函数所在的线程我们称之为 主线程(main线程) ,其余创建的线程称之为子线程。 程序中默认只有一个进程,fork()函数调用,2进行 程序中默认只有一个线程,pthread_create()函数调用,2个线程。 #include pthread.h int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

    2024年02月09日
    浏览(44)
  • Python Flask Web开发二:数据库创建和使用

    数据库在 Web 开发中起着至关重要的作用。它不仅提供了数据的持久化存储和管理功能,还支持数据的关联和连接,保证数据的一致性和安全性。通过合理地设计和使用数据库,开发人员可以构建强大、可靠的 Web 应用程序,满足用户的需求。这里介绍:SQLAlchemy 安装pymysql和

    2024年02月10日
    浏览(59)
  • 一、Flink使用异步算子+线程池查询MySQL

    目录 Flink异步算子使用介绍 使用Flink异步算子+多线程异步查询MySQL 相关阅读 1 Flink使用异步算子请求高德地图获取位置信息 1、概述 1)Flink异步算子使用介绍 1.异步与同步概述 同步:向数据库发送一个请求然后一直等待,直到收到响应。在许多情况下,等待占据了函数运行的

    2024年02月14日
    浏览(42)
  • Python创建多线程的两种常用方法

    这篇文章主要为大家详细介绍了Python中创建多线程的两种常用方法,文中的示例代码简洁易懂,对我们掌握Python有一定的帮助,需要的可以收藏一下 经过总结,Python创建多线程主要有如下两种方法: 函数 类 接下来,我们就来揭开多线程的神秘面纱。 在Python3中,Python提供了

    2024年02月15日
    浏览(34)
  • 13-1_Qt 5.9 C++开发指南_多线程及QThread 创建多线程程序_ThreadSignal

    一个应用程序一般只有一个线程,一个线程内的操作是顺序执行的,如果有某个比较消耗时间的计算或操作,比如网络通信中的文件传输,在一个线程内操作时,用户界面就可能会冻结而不能及时响应。这种情况下,可以创建一个单独的线程来执行比较消耗时间的操作,并与

    2024年02月14日
    浏览(45)
  • 线程的创建和使用(二)

    Thread类是JVM用来管理线程的一个类,换句话说,每个线程都有唯一一个的Thread对象与之关联。 1.1、Thread的常见方法 方法 说明 Thread() 创建线程对象 Thread(Runnable target) 使用Runnable对象创建线程对象 Thread(String name) 创建线程对象并命名 Thread(Runnable target,String name) 使用Runnable对象创

    2024年02月09日
    浏览(30)
  • 使用了Python语言和Flask框架。创建一个区块链网络,允许用户通过HTTP请求进行交互,如包括创建区块链、挖矿、验证区块链等功能。

    目录 大概来说: 二、代码注释 1.添加交易方法(add_transaction函数) 2.添加新的节点(add_node 函数) 3、替换链的方法(replace_chain函数) 总结 定义了一个名为Blockchain的类,用于构建区块链。 在Blockchain类中,定义了创建区块、获取上一个区块、工作量证明、哈希计算、验证区

    2024年04月25日
    浏览(34)
  • Java多线程---线程的创建(Thread类的基本使用)

    本文主要介绍Java多线程的相关知识, Thread的创建, 常用方法的介绍和使用, 线程状态等. 文章目录 前言 一. 线程和Thread类 1. 线程和Thread类 1.1 Thread类的构造方法 1.2 启用线程的相关方法 2. 创建第一个Java多线程程序 3. 使用Runnable对象创建线程 4. 使用内部类创建线程 5. 使用Lamba

    2024年02月03日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包