concurrent.futures
我们在以往创建线程或进程的时候都会使用threading与multiprocessing模块进行创建。
那么在本章节学习完成后就不要使用这两种方式创建线程或者进程了,而是应当使用concurrent.futures所提供的执行器来构建线程或进程并执行任务。
concurrent.futures提供了2种执行器,如下所示,它们的接口使用也都一模一样:
from concurrent.futures import ThreadPoolExecutor # 线程池执行器
from concurrent.futures import ProcessPoolExecutor # 进程池执行器
注意,在Python2中是没有线程池执行器的。
使用执行器和不使用执行器创建线程或进程两者2有什么不同呢?如下表所示:
普通线程 | 执行器 | |
---|---|---|
创建线程 | 惰性创建,需要执行任务时再创建线程 | 及早创建,在初始化执行器时就会创建一堆线程 |
提交任务 | 同步的提交任务,获取结果时需要等待,完成任务的线程会立即销毁 | 异步的提交任务,获取结果时将采用回调机制,完成任务的线程会立即返回至执行器中 |
销毁线程 | 任务完成后立即销毁线程 | 删除执行器或解释器析构时销毁线程 |
我们可以从这张图中看出2者的差距:
线程的创建和销毁是需要额外占据系统资源的,所以使用线程池执行器来管理线程性能上也会得到一定的提升。
执行器对象
方法大全
下面是执行器所提供的方法,用于创建子线程以及给子线程派发并执行任务:
方法 | 描述 |
---|---|
ThreadPoolExecutor(max_workers=int) | 返回一个线程池执行器对象,可指定该池中工作线程的最大数量 |
submit(fn, *args, **kwargs) | 异步提交任务fn并派发给线程池执行器中的线程进行任务执行,返回期程对象 |
map(fn, *iterables, timeout=None, chunksize=1) | 类似于内置函数map,它将map中fn的任务提交变更为异步的 |
shutdown(wait=True) | 等待,类似于join()方法。在所有任务完成后关闭线程池执行器 |
基本使用
下面将