一、基类Executor

Executor类是ThreadPoolExecutor 和ProcessPoolExecutor 的基类。它为我们提供了如下方法:

submit(fn, *args, **kwargs):提交任务。以 fn(*args **kwargs) 方式执行并返回 Future 对像。

fn:函数地址。

*args:位置参数。

**kwargs:关键字参数。

map(func, *iterables, timeout=None, chunksize=1):

func:函数地址。

iterables:一个可迭代对象,以迭代的方式将参数传递给函数。

timeout:这个参数没弄明白,如果是None等待所有进程结束。

chunksize:使用 ProcessPoolExecutor 时,这个方法会将 iterables 分割任务块,并作为独立的任务提交到执行池中。这些块的数量可以由 chunksize 指定设置。 对很长的迭代器来说,设置chunksize 值比默认值 1 能显著地提高性能。 chunksize 对 ThreadPoolExecutor 没有效果。

shutdown(wait=True):如果为True会等待线程池或进程池执行完成后释放正在使用的资源。如果 wait 为 False,将立即返回,所有待执行的期程完成执行后会释放已分配的资源。 不管 wait 的值是什么,整个 Python 程序将等到所有待执行的期程完成执行后才退出。

二、线程池对象

ThreadPoolExecutor 是 Executor 的子类,下面介绍ThreadPoolExecutor 的参数。

class concurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=()):

max_workers:线程池的数量。

thread_name_prefix:线程名前缀。默认线程名ThreadPoolExecutor-线程数。

initializer:一个函数或方法,在启用线程前会调用这个函数(给线程池添加额外任务)。

initargs :以元祖的方式给initializer中的函数传递参数。

这里需要说明的是除了max_workers这个参数外其它三个参数基本很少用。max_workers很好理解就是线程池的数量。

下面来说initializer和initargs 这两个奇怪的家伙。

示例一:

  1. from concurrent.futures import ThreadPoolExecutor
  2. def work():
  3. print('工作线程')
  4. def test(num):
  5. print('test:',num)
  6. executor = ThreadPoolExecutor(max_workers=2,initializer=test(7)) # 开启2个线程 initializer指定参数test(7)
  7. executor.submit(work)
  8. executor.submit(work)
  9.  
  10. # 打印内容如下
  11. test: 7
  12. 工作线程
  13. 工作线程

示例二:

  1. from concurrent.futures import ThreadPoolExecutor
  2. def work():
  3. print('工作线程')
  4. def test(num):
  5. print('test:',num)
  6. executor = ThreadPoolExecutor(max_workers=2,initializer=test,initargs=(7,)) # 这里我们使用initargs=(7,)的方式给test传递参数。
  7. executor.submit(work)
  8. executor.submit(work)
  9.  
  10. # 打印内容如下
  11. test: 7
  12. 工作线程
  13. 工作线程
  14. test: 7

通过示例一和示例二我们可以发现initializer=test(7)时,test函数只被调用了1次,当initializer=test,initargs=(7,)时,test被调用了2次。具体原因没有去分析。感觉没什么用。以后有时间看看源码在补上。

三、进程池对象

ProcessPoolExecutor 也是 Executor 的子类,下面是ProcessPoolExecutor 参数介绍:

class concurrent.futures.ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=())

max_workers:工作进程数。如果 max_workers 为 None 或未给出,它将默认为机器的处理器个数。 如果 max_workers 小于等于 0,则将引发 ValueError。 在 Windows 上,max_workers 必须小于等于 61,否则将引发 ValueError。 如果 max_workers 为 None,则所选择的默认最多为 61,即使存在更多处理器。

mp_context :可以是一个多进程上下文或是 None。 它将被用来启动工作进程。 如果 mp_context 为 None 或未给出,将使用默认的多进程上下文。

initializer:一个函数或方法,在启用线程前会调用这个函数。

initargs :以元祖的方式给initializer中的函数传递参数。

关于说initializer和initargs 与ThreadPoolExecutor 类似这里不多说了。


四、创建线程池

  1. from concurrent.futures import ThreadPoolExecutor
  2. import time
  3. def work(num):
  4. time.sleep(1)
  5. print('工作线程:',num)
  6. if __name__ == '__main__':
  7. executor = ThreadPoolExecutor(max_workers=5) # 创建线程池,数量为5
  8. for i in range(5):
  9. executor.submit(work, i)
  10. print('主线程')
  11.  
  12. # 打印内容如下
  13. 主线程
  14. 工作线程: 0
  15. 工作线程: 1
  16. 工作线程: 2
  17. 工作线程: 3
  18. 工作线程: 4
  19. # 使用shutdown等待所有线程结束后在打印主线程
  20. from concurrent.futures import ThreadPoolExecutor
  21. import time
  22. def work(num):
  23. time.sleep(1)
  24. print('工作线程:',num)
  25. if __name__ == '__main__':
  26. executor = ThreadPoolExecutor(max_workers=5) # 创建线程池,数量为5
  27. for i in range(5):
  28. executor.submit(work, i)
  29. executor.shutdown(wait=True) # 等待线程池结束
  30. print('主线程')
  31.  
  32. # 打印内容如下
  33. 工作线程: 0
  34. 工作线程: 1
  35. 工作线程: 2
  36. 工作线程: 3
  37. 工作线程: 4
  38. 主线程

如果想要在线程执行的过程中添加额外的功能,可以使用initializer参数,如下:

  1. from concurrent.futures import ThreadPoolExecutor
  2.  
  3. def work(num):
  4. print('工作线程:',num)
  5. def test(num):
  6. print('额外任务:',num)
  7. if __name__ == '__main__':
  8. executor = ThreadPoolExecutor(max_workers=5,initializer=test,initargs=(7,)) # 添加额外任务
  9. for i in range(5):
  10. executor.submit(work, i)
  11. executor.shutdown(wait=True)
  12. print('主线程')
  13.  
  14. # 打印内容如下
  15. 额外任务: 7
  16. 工作线程: 0
  17. 额外任务: 7
  18. 工作线程: 1
  19. 额外任务: 7
  20. 工作线程: 2
  21. 额外任务: 7
  22. 工作线程: 3
  23. 额外任务: 7
  24. 工作线程: 4
  25. 主线程

五、进程池

进程池与线程池用法基本一致,只是名字和实现不一样而已。

  1. from concurrent.futures import ProcessPoolExecutor
  2. import time
  3. def work(num):
  4. time.sleep(1)
  5. print('工作进程:',num)
  6. if __name__ == '__main__':
  7. executor = ProcessPoolExecutor(max_workers=5) # 创建进程池,数量为5
  8. for i in range(5):
  9. executor.submit(work, i)
  10. print('主线程')
  11.  
  12. # 打印内容如下
  13. 主线程
  14. 工作进程: 0
  15. 工作进程: 1
  16. 工作进程: 2
  17. 工作进程: 3
  18. 工作进程: 4
  19.  
  20. # 使用shutdown等待所有线程结束后在打印主线程
  21. from concurrent.futures import ProcessPoolExecutor
  22. import time
  23. def work(num):
  24. time.sleep(1)
  25. print('工作进程:',num)
  26. if __name__ == '__main__':
  27. executor = ProcessPoolExecutor(max_workers=5) # 创建进程池,数量为5
  28. for i in range(5):
  29. executor.submit(work, i)
  30. executor.shutdown(wait=True) # 等待进程池结束
  31. print('主线程')
  32. # 打印内容如下
  33. 工作进程: 0
  34. 工作进程: 1
  35. 工作进程: 2
  36. 工作进程: 3
  37. 工作进程: 4
  38. 主线程

如果想要在线程执行的过程中添加额外的功能,可以使用initializer参数,如下:

  1. from concurrent.futures import ProcessPoolExecutor
  2.  
  3. def work(num):
  4. print('工作进程:',num)
  5. def test(num):
  6. print('额外任务:',num)
  7. if __name__ == '__main__':
  8. executor = ProcessPoolExecutor(max_workers=5,initializer=test,initargs=(7,)) # 添加额外任务
  9. for i in range(5):
  10. executor.submit(work, i)
  11. executor.shutdown(wait=True)
  12. print('主线程')
  13.  
  14. # 打印内容如下
  15. 额外任务: 7
  16. 工作进程: 0
  17. 工作进程: 1
  18. 工作进程: 2
  19. 工作进程: 3
  20. 工作进程: 4
  21. 额外任务: 7
  22. 额外任务: 7
  23. 额外任务: 7
  24. 额外任务: 7
  25. 主线程

六、Future Objects

future类封装了可调用文件的异步执行。future的实例由executor.submit()时被创建的,除了测试之外不应该直接实例化future对象,所以为了获取future对象我们可以f=executor.submit()即可。

class concurrent.futures.Future类中的方法:

cancel():尝试取消执行线程池中的函数调用。如果调用当前正在执行或已完成运行,并且无法取消,则方法将返回false,否则调用将被取消,方法将返回true。

cancelled():如果线程池中的函数执行成功返回True,调用失败返回false。

running():如果线程池中的调用当前正在执行且无法取消,则返回true。

done():如果呼叫成功取消或完成运行,则返回true。否则返回false

result(timeout=None):返回线程函数的返回值。如果线程函数未执行完成,则此方法将最多等待timeout秒,如果线程函数未在超时秒内完成,则将引发concurrent.futures.TimeoutError。超时可以是int或float。如果未指定超时 timeout=None,则会阻塞,一直等待函数执行完成。如果在线程函数完成之前使用future对象取消了执行,则将引发CancelederRor。如果调用raised,此方法将引发相同的异常。

exception(timeout=None):返回线程函数引发的异常。如果线程函数尚未完成,则此方法将最多等待timeout秒。如果线程函数未在超时秒内完成,则将引发concurrent.futures.TimeoutError。超时可以是int或float。如果未指定超时或无超时timeout=None,则会一直等待。如果在线程函数完成之前使用future对象取消了执行,则将引发CancelederRor如果线程函数完成但未引发,则返回None。

add_done_callback(fn):将可调用fn附加到future对象。当future对象被取消或结束运行时,将调用fn,其中future对象是惟一的参数。添加的可调用对象是按照添加顺序调用的,并且总是在属于添加它们的进程的线程中调用。如果Callable引发异常子类,它将被记录并忽略。如果可调用引发BaseException子类,则行为未定义。


七、Module Functions

concurrent.futures.wait(fs, timeout=None, return_when=ALL_COMPLETED):将fs绑定一个future实例,如果future执行完成或取消执行fs函数。

fs:fs是一个函数绑定在future实例(可能由不同的执行器实例创建)。返回2个命名元组的集合。第一组名为“done”,包含等待完成,完成前(完成或future对象取消)。第二组名为“not_done”,包含未完成的future(未完成或正在运行的future)。

timeout:如果为None一直等待,否则会等待timeout秒。

return_when :必须是如下范围。

Constant

Description

FIRST_COMPLETED

当任何future 完成或取消或者线程函数执行完成时。

FIRST_EXCEPTION

当future通过引发异常而结束时,线程函数将返回。如果没有future引发异常,那么它相当于所有已完成的。

ALL_COMPLETED

当所有future完成或取消时,函数将返回。

concurrent.futures.as_completed(fs, timeout=None):返回一个future迭代器。

fs:可迭代对象的future。

timeout:超时时间,如果为None会一直阻塞直到执行完成。否则将等待timeout秒。

  1. from concurrent.futures._base import as_completed
  2. from concurrent.futures import ThreadPoolExecutor
  3.  
  4. def work(num):
  5. return num ** 2
  6. if __name__ == '__main__':
  7. executor = ThreadPoolExecutor(max_workers=5)
  8. future_list = [] # 存放future对象
  9. for i in range(5):
  10. future_list.append(executor.submit(work, i))
  11. for future in as_completed(future_list): # 这是一个无聊的用法
  12. res = future.result()
  13. print(f'结果:{res}') # 打印工作线程返回的结果
    # 打印结果如下

结果:0
结果:4
结果:16
结果:1
结果:9

  1.  

参考文档:https://docs.python.org/3/library/concurrent.futures.html

concurrent.futures模块简单介绍(线程池,进程池)的更多相关文章

  1. 使用concurrent.futures模块中的线程池与进程池

    使用concurrent.futures模块中的线程池与进程池 线程池与进程池 以线程池举例,系统使用多线程方式运行时,会产生大量的线程创建与销毁,创建与销毁必定会带来一定的消耗,甚至导致系统资源的崩 ...

  2. concurrent.futures模块(进程池&线程池)

    1.线程池的概念 由于python中的GIL导致每个进程一次只能运行一个线程,在I/O密集型的操作中可以开启多线程,但是在使用多线程处理任务时候,不是线程越多越好,因为在线程切换的时候,需要切换上下文 ...

  3. concurrent.futures模块(进程池/线程池)

    需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...

  4. 线程池、进程池(concurrent.futures模块)和协程

    一.线程池 1.concurrent.futures模块 介绍 concurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor:线程池,提供异步调用 Pro ...

  5. Python并发编程之线程池/进程池--concurrent.futures模块

    一.关于concurrent.futures模块 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/ ...

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

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

  7. Python3【模块】concurrent.futures模块,线程池进程池

    Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/销毁进程或者线程是非常消耗资源的,这个时候我们就要 ...

  8. 创建进程池与线程池concurrent.futures模块的使用

    一.进程池. 当并发的任务数量远远大于计算机所能承受的范围,即无法一次性开启过多的任务数量就应该考虑去 限制进程数或线程数,从而保证服务器不会因超载而瘫痪.这时候就出现了进程池和线程池. 二.conc ...

  9. concurrent.futures模块 -----进程池 ---线程池 ---回调

    concurrent.futures模块提供了高度封装的异步调用接口,它内部有关的两个池 ThreadPoolExecutor:线程池,提供异步调用,其基础就是老版的Pool ProcessPoolE ...

随机推荐

  1. HTML5 3D 在智慧物业/地产管理系统中的应用

    概述 该博文主要展示采用 HT for Web 提供的可视化技术,对智慧房产.智慧物业相关方向的可视化呈现做的一点尝试. 传统的 智慧房产/楼宇自动化/智慧物业 常会采用 BIM(建筑信息模型 Bui ...

  2. 深蓝词库转换2.5发布——支持微软五笔,支持Linux和macOS和更多命令行功能

    最近利用晚上的时间,对很久没有新版本发布的深蓝词库转换进行了版本升级.本次升级主要包含的功能包括: 一.支持Win10自带的微软五笔输入法用户自定义短语的导入导出. 1.在转换输入法词库列表中选择“W ...

  3. 如何优雅规避NPE

    项目中尤其是在持久层,难免会有大量的针对集合,对象,字符串的操作,为了程序的健壮性,我们不得不进行判空,像下面箭头式编码吗? if(null!=person){ ... if(null!=addres ...

  4. Docker 系列之 常用镜像

    Ubuntu 实战 操作 # 拉取 18.04 版本的 Ubuntu 镜像 docker pull ubuntu:latest # 以交互方式运行并进入 ubuntu 容器环境 docker run ...

  5. windows下cocos2d-x环境搭建

    该教程使用的cocos2dx的版本为3.14,3之后的大概都差不多 Python环境搭建: cocos2dx在windows上新建工程需要用到python脚本,安装python-2.7.x,可以上py ...

  6. 关于hover与after,before已及first-letter,first-line的联用

    0920自我总结 关于hover与after,before已及first-letter,first-line的联用 一.写法 元素:hover::after{样式} 元素:hover::before{ ...

  7. word-break、word-wrap、white-space区别

    <div id="box"> Hi  , This is a incomprehensibilities long word. </br> 你好  , 这 ...

  8. Java 网络编程初探

    Java 网络编程 网络编程 网络编程:进行服务器端与客户端编程的开发操作实现. java.net:网络操作包 B/S结构: 浏览器/服务器模式(Browser/Server) 不在开发客户端代码 开 ...

  9. ebs oracle YTD期间费用

    select PERIOD_NAME, SEGMENT3, SEGMENT3_DESC, sum(case when SEGMENT2 = '1011' then ACCOUNTED_ACCRUAL ...

  10. iTerm2 使用代理

    0x00 事件 因为 brew 安装极慢,所以需要 iTerm2 设置代理解决速度问题. 0x01 解决 代理软件开启本地 Http 端口: iTerm 设置代理: $ vim ~/.zshrc # ...