一、线程池简介

传统多线程方案会使用“即时创建,即时销毁”的策略。尽管与创建进程相比,创建线程的时间已经大大的缩短,但是如果提交给线程的任务时执行时间较短,而且执行次数及其频繁,那么服务器将处于不停的创建线程,销毁线程的状态。

一个线程的运行时间可以分为三部分:线程的启动时间、线程体的运行时间和线程的销毁时间。在多线程处理的情景中,如果线程不能被重用,就意味着每次线程运行都要经过启动、销毁和运行3个过程。这必然会增加系统相应的时间,减低了效率。

线程池在系统启动时即创建大量空闲的线程,程序只要将一个函数提交给线程池,线程池就会启动一个空闲的线程来执行它。当该函数执行结束后,该线程并不会死亡,而是再次返回到线程池中变成空闲状态,等待执行下一个函数,因此能够避免多次创建线程,从而节省线程创建和销毁的开销,能带来更好的性能和稳定性。

此外,使用线程池可以有效地控制系统中并发线程的数量。当系统中包含有大量的并发线程时,会导致系统性能急剧下降,甚至导致Python解释器崩溃,而线程池的最大线程数参数可以控制系统中并发线程的数量不超过此数。

服务器CPU数有限,能够同时并发的线程数有限,并不是开得越多越好,以及线程切换时有开销的,如果线程切换过于频繁,反而会使性能降低。python线程池大小设置参见:python3 ThreadPoolExecutor 线程池大小设置_whatday的博客-CSDN博客_python线程池大小

线程池适用于:突发性大量请求或需要大量线程完成任务,但实际任务处理时间较短的场景

二、线程池在python中的应用

从python3.2开始,标准库提供了concurrent.futures模块,它提供了两个子类:ThreadPoolExecutor和ProcessPoolExecutor。其中ThreadPoolExecutor用于创建线程池,而ProcessPoolExecutor用于创建进程池。不仅可以自动调度线程,还可以做到:

• 主线程可以获取某一个线程(或任务)的状态,以及返回值

• 当一个线程完成的时候,主线程能够立即知道

• 让多线程和多进程编码接口一致

使用线程池/进程池来管理并发编程,只要将相应的 task 函数提交给线程池/进程池,剩下的事情就由线程池/进程池来搞定。

ThreadPoolExecutor构造函数有两个参数:

一个是max_workers参数,用于指定线程池的最大线程数,如果不指定的话则默认是CPU核数的5倍。

另一个参数是thread_name_prefix,它用来指定线程池中线程的名称前缀(可选),如下:

threadPool = ThreadPoolExecutor(max_workers=self.max_workers, thread_name_prefix="test_")

Exectuor 提供了如下常用方法:

方法 描述
submit(fn, *args, **kwargs) 将 fn 函数提交给线程池。*args 代表传给 fn 函数的参数,**kwargs 代表以关键字参数的形式为 fn 函数传入参数
map(func,*iterables, timeout=None, chunksize=1) 该函数类似于全局函数 map(func, *iterables),只是该函数将会启动多个线程,以异步方式立即对 iterables 执行 map 处理
shutdown(wait=True) 关闭线程池。wait=True,等待池内所有任务执行完毕回收完资源后才继续;wait=False,立即返回,并不会等待池内的任务执行完毕。但不管wait参数为何值,整个程序都会等到所有任务执行完毕

程序将 task 函数提交(submit)给线程池后,submit 方法会返回一个 Future 对象,Future 类主要用于获取线程任务函数的返回值。由于线程任务会在新线程中以异步方式执行,因此线程执行的函数相当于一个“将来完成”的任务,所以 Python 使用 Future 来代表。

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 函数

线程池用完后,应调用线程池的shutdown()方法,关闭线程池。也可使用with语句来管理线程池,可避免手动关闭线程池

示例一(使用submit方式):

from concurrent.futures import ThreadPoolExecutor # 导入ThreadPoolExecutor模块
import timemax_workers = 5
t = []
t1 = time.time()# 作为线程任务的函数
def task(x, y):return x + ythreadPool = ThreadPoolExecutor(max_workers)    # 创建最大线程数为max_workers的线程池for i in range(20):     # 循环向线程池中提交task任务future = threadPool.submit(task, i, i+1)t.append(future)# 若不需要获取返回值,则可不需要下面两行代码
for i in t:print(i.result())   # 获取每个任务的返回值,result()会阻塞主线程threadPool.shutdown()   # 阻塞主线程,所有任务执行完后关闭线程池
print(time.time() - t1)

示例二(使用map方式):

from concurrent.futures import ThreadPoolExecutor    # 导入ThreadPoolExecutor模块max_workers = 5
t = []
t1 = time.time()# 作为线程任务的函数
def task(x):return x + (x + 1)args = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)with ThreadPoolExecutor(max_workers) as threadPool:   # 创建最大线程数为max_workers的线程池results = threadPool.map(task, args)    # 启动线程,并收集每个线任务的返回结果# 若无返回值,则可不需要下面两行代码for i in results:print(i)   

示例三:

as_complete():是一个生成器,在没有任务完成的时候会阻塞,在有某个任务完成的时候会yield这个任务,执行语句,继续阻塞,循环到所有任务结束,先完成的任务会先通知主线程

from concurrent.futures import ThreadPoolExecutor, as_completed
import timemax_workers = 5
t = []
t1 = time.time()# 作为线程任务的函数
def task(x, y):return x + ydef handle_result(future):print(future.result())with ThreadPoolExecutor(max_workers) as threadPool:    # 创建最大线程数为max_workers的线程池for i in range(20):     # 循环向线程池中提交task任务future = threadPool.submit(task, i, i+1)t.append(future)# 若不需要获取返回值,则可不需要下面两行代码for future in as_completed(t):  # as_completed,哪个先完成就先处理哪个,会阻塞主线程,直到完成所有,除非设置timeoutfuture.add_done_callback(handle_result)

【python高阶编程】python线程池简单应用相关推荐

  1. Java高并发编程:线程池

    这里首先介绍了java5中的并发的小工具包:java.util.concurrent.atomic,然后介绍了线程池的概念,对使用java5的方式创建不同形式的线程进行了演示,之后介绍了两个 对象:C ...

  2. 《转载》Python并发编程之线程池/进程池--concurrent.futures模块

    本文转载自 Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mul ...

  3. python高阶函数map_简单了解python高阶函数map/reduce

    高阶函数map/reduce Python内建了map()和reduce()函数. 我们先看map.map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每 ...

  4. 廖雪峰讲python高阶函数求导公式_一文读懂Python 高阶函数

    高阶函数 将函数作为参数传入,这样的函数称为高阶函数.函数式编程就是指这种高度抽象的编程范式. 变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函 ...

  5. python高阶函数看不懂_Python进阶:高阶函数的详细说明

    这篇文章讲述了Python进阶:高阶函数的详细说明有需要的朋友可以参考 函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单 ...

  6. 廖雪峰讲python高阶函数求导公式_高阶函数 - 廖雪峰 Python 2.7 中文教程

    高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...

  7. python高阶学习之一:c++调用python

    python高阶学习之一:c++调用python python已经成为当今人工智能和数据分析的主流语言,掌握python就好像拿到了进入AI分析殿堂的门票一样,无论如何任何事情都要从一点一滴做起,不要 ...

  8. 廖雪峰讲python高阶函数求导_高阶函数 - 廖雪峰的Python2.7教程 - 广州尚鹏

    高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...

  9. 廖雪峰讲python高阶函数-高阶函数

    高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...

  10. 廖雪峰讲python高阶函数求导_高阶函数 · 廖雪峰的Python3.x教程 · 看云

    [TOC] ### 引入 高阶函数英文叫`Higher-order function`.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. ### 变量可以指向函数 以Python内置的求绝对值 ...

最新文章

  1. python处理pdf实例_Python实战-从菜鸟到大牛的进阶之路pdf_Python教程
  2. C++简单使用Jsoncpp来读取写入json文件
  3. plotly可视化绘制双子图(subplots)
  4. MacApp开发Error Domain=NSURLErrorDomain Code=-1003 A server with the specified hostname could not be
  5. mxnet加载保存部分参数
  6. 数据机房建设常用材料有哪些?
  7. 国家电网和南方电网还傻傻分不清?
  8. [MEGA DEAL]完整的Java捆绑包(96%折扣)
  9. 远程拷贝代码 指定端口
  10. 【转】Struts2 严重: Dispatcher initialization failed java.lang.RuntimeException
  11. Java 会是未来第一编程语言吗?
  12. python numpy和pandas做数据分析时去掉科学记数法显示
  13. Linux下安装Win10虚拟机
  14. python入门基础知识(九):函数
  15. PHP 开发杂谈:对后端开发的思考
  16. java学习之路2--简单工厂模式实现饮料自动贩卖机
  17. 解决Chromedriver报错Original error: chrome not reachable
  18. HTML“计算机输出”标签 codekbdsampttvarpre
  19. adob animate_Chrome报告“ Adob​​e Flash Player已被阻止,因为它已过期。”
  20. android 内部存储 共享,android存储:共享参数、内部存储、拓展存储

热门文章

  1. 计算机二级java和c哪个难,计算机二级最好考哪个 考试难度怎么样
  2. C语言练习-[1008]成绩评定
  3. 三个有用的SQL辅助工具
  4. 居家养老管理系统设计
  5. 《码农翻身》之浪潮之巅的Web
  6. 安装Esxi6.5时出现 menu.c32:not a COM32R image 的处理方法
  7. c语言调用子程序实例,C语言程序调用汇编语言子程序
  8. VBA教程初级(四):声明数组
  9. 用grub4dos制作U盘启动盘winpe+红叶dos+maxdos+veket+linuxmint
  10. p2p终结者局域网控制软件的介绍和用法