使用concurrent.futures模块快捷方便的进行多线程(池)或多进程(池)操作(python)

在这里插入图片描述
之前已经介绍过了python的multiprocessing包相关的使用方法,实际上在python3.2版以后新加入了concurrent.futures模块。这个模块拥有线程池及进程池执行对象即Executor()。对比起多线程和多进程的其它模块,此模块包含了两种多进程多线程两种方式,且使用更加简单。使用时根据自身需要选择使用哪一个包。
concurrent.futures模块中含有ThreadPoolExecutor与ProcessPoolExecutor两个池执行器,操作方式类似,本文主要以ThreadPoolExecutor为例进行介绍


future对象

Future对象能够储存异步执行的任务,即其能代表一个正在执行的任务,这也说明了future对象的产生和运行是非阻塞的。future对象所接受的任务都是由ThreadPoolExecutor或者ProcessPoolExecutor产生的,future对象储存这些任务。通过调用future对象能够了解到这些任务的完成情况。因此future对象具有一系列的方法如下表:

方法作用
cancel()尝试取消调用,如果该调用正在执行中,无法取消,本方法返回 False,其他情况下调用会被取消,并返回 True
cancelled()判断是否被取消
running()判断是否正在运行
result()获取结果
add_done_callback()添加回调函数
done()判断是否结束
exception获取异常

submit()

一个submit运行一次需要传入一个函数和执行一次函数需要的参数。因此调用一次submit只能执行单个任务,要使用submit执行多个任务就需要将不同的参数分配给submit,从而执行多线程任务。

例:

from concurrent.futures import ThreadPoolExecutor    # 导入线程池执行器
import time                                          # 导入time模块,计算花费时间

def test(g):
    time.sleep(2)                   # 函数中休眠2s
    return g                        # 设置返回值

if __name__ == '__main__':
    record = []                     # 创建列表放置后续产生的future对象
    t = time.time()                 # 记录开始运行的时间
    with ThreadPoolExecutor(max_workers=10) as executor:  
    # 线程池的使用方式,由于是with方式,因此不需要自己关闭。同时线程池会自动join()
    # 当然也可以使用executor = ThreadPoolExecutor(max_workers=4),但需要在使用结束后使用
    # shutdown方法,才能阻塞主线程。 代码也贴上啦,在下面。
        for l in list(range(5)):			  # 创建一个参数列表用于后续传入函数
            future = executor.submit(test,l)  
            # 传入要执行的函数及参数,返回的是一个future对象,注意这里不要调用,此处调用会使线程阻塞。
            record.append(future)             # 将对象添加到record列表中
        for future in record:               
            print(future.result())			  # 打印每个返回值
    print('程序结束')       	# 测试主线程是否阻塞
    print(time.time()-t)   	# 打印程序花费时间

结果如下:

在这里插入图片描述
可以看到运行结果达到了预期,即运行使用了多线程,本该运行10s的任务在2s内完成了。

另一种方法

from concurrent.futures import ThreadPoolExecutor
import time

def test(g):
    time.sleep(2)
    return g

if __name__ == '__main__':
	record = []
    t = time.time()
    pool = ThreadPoolExecutor(max_workers=10)
    for l in list(range(5)):
        res = pool.submit(test,l)
        record.append(res)
    for p in record:
        print(p.result())
    pool.shutdown()    # 关闭线程池,同时起到join的效果
    print('程序结束')
    print(time.time()-t)

map()

map同submit一样都是执行任务的,但是map可以同时添加多个任务。将某个可迭代的参数库与某函数直接map起来,较submit更为方便。

例:

from concurrent.futures import ThreadPoolExecutor
import time

def test(g):
    time.sleep(2)
    return g
    
if __name__ == '__main__':
    t = time.time()
    with ThreadPoolExecutor(max_workers=10) as pool:
        results = pool.map(test,range(5))   # 产生一个生成器generator,可以从中获取结果
        for result in results:
            print(result)
    print('程序结束')
    print(time.time()-t)

运行结果如下:

在这里插入图片描述

wait()与as_completed()

  • wait方法可以让主线程阻塞,直到满足设定的要求。有三种条件ALL_COMPLETED, FIRST_COMPLETED,FIRST_EXCEPTION
  • as_completed同样也与主进程阻塞有关(即需要所有future对象都运行结束才结束阻塞)。

看例子理解一下吧,例:


from concurrent.futures import ThreadPoolExecutor,wait,as_completed,FIRST_COMPLETED
import time

def test(g):
    time.sleep(2)       
    return g

if __name__ == '__main__':
    record = []
    t = time.time()
    with ThreadPoolExecutor(max_workers=10) as executor:
        for l in list(range(5)):
            future = executor.submit(test,l)
            record.append(future)
        wait(record, return_when=FIRST_COMPLETED)    # 第一次完成后即不再阻塞
        print('第一次运行结束')         # 测试第一次完成后是否不再阻塞
        for future in as_completed(record):   # 其实就相当于之前的shutdown操作
            print(future.result())            # 并不按顺序提取,谁先完成就先打印,此处看不出来
    print('程序结束')
    print(time.time()-t)
    

结果如下:

在这里插入图片描述

叮!

此模块中多进程和多线程的使用方式应该差不多,这里就不再赘述咯!

多进程相关的内容看了很多,也写了好几篇,因为感觉挺重要的。虽说花了一些时间,但之后用上的时候应该会更加熟练一点吧!本文介绍的内容应该也足以应付平常用到的工作了吧。

参考:concurrent.futures进行并发编程
参考:Python 中 concurrent.futures 模块使用说明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值