文章目录
一、进程(线程)池介绍
在程序实际处理问题过程中,忙时会有成千上万的任务需要被执行,闲时可能只有零星任务。那么在成千上万个任务需要被执行的时候,我们就需要去创建成千上万个进程么?首先,创建进程需要消耗时间,销毁进程也需要消耗时间。第二即便开启了成千上万的进程,操作系统也不能让他们同时执行,这样反而会影响程序的效率。因此我们不能无限制的根据任务开启或者结束进程。那么我们要怎么做呢?
在这里,要给大家介绍一个进程池的概念,定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中的进程来处理任务,等到处理完毕,进程并不关闭,而是将进程再放回进程池中继续等待任务。如果有很多任务需要执行,池中的进程数量不够,任务就要等待之前的进程执行任务完毕归来,拿到空闲进程才能继续执行。也就是说,池中进程的数量是固定的,那么同一时间最多有固定数量的进程在运行。这样不会增加操作系统的调度难度,还节省了开闭进程的时间,也一定程度上能够实现并发效果。
二、concurrent.fututres 模块
2.1 ProcessPoolExecutor
类–进程池开启
进程池类的导入:from concurrent.fututres import ProcessPoolExecutor
实例化:``pool_p = ProcessPoolExecutor( 整数 ): 实例化获得一个进程池, 参数传入一个整数,代表进程池的大小
不传的话会默认开设当前计算机CPU 个数的进程
2.2 方法及属性介绍
2.2.1 异步提交任务–submit 方法
pool_p.submit(task,n=i)
: task
–提交的任务,逗号之后可以按照位置参数或者关键字参数传入task
所需的参数;
提交任务分为同步提交与异步提交–详见文章 怎样理解阻塞非阻塞与同步异步的区别?
submit 方法
:会有一个返回值,返回一个Future
对象:<Future at 内存地址 state=...... returned .....>
Future
对象会有一个result
方法
submit 方法
演示
from concurrent.futures import ProcessPoolExecutor
import time
pool1 = ProcessPoolExecutor(5)
def task(n):
print(n)
time.sleep(2)
if __name__ == '__main__':
for i in range(5):
pool1.submit(task, i)
print('main process')
由结果不难发现submit 方法
是异步提交任务
from concurrent.futures import ProcessPoolExecutor
import time
pool1 = ProcessPoolExecutor(5)
def task(n):
print(n, end=" ")
time.sleep(1)
if __name__ == '__main__':
for i in range(20):
pool1.submit(task, i)
print('main process')
2.2.2 result
方法
submit
方法返回的Future
对象会有一个result
方法
result
方法 会返回**提交的任务最终返回的结果 **
from concurrent.futures import ProcessPoolExecutor
import time
pool1 = ProcessPoolExecutor(5)
def task(n):
print(n,end=' ')
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
res=pool1.submit(task, i)
print(res.result())
print('main process')
修改提交任务的返回值–验证
from concurrent.futures import ProcessPoolExecutor
import time
pool1 = ProcessPoolExecutor(5)
def task(n):
print(n,end=' ')
time.sleep(1)
return n**2
if __name__ == '__main__':
for i in range(5):
res=pool1.submit(task, i)
print(res.result())
print('main process')
如何将所有的任务全部提交运行结束之后,再统一获得结果
2.2.3 shutdown 方法
关闭线程池,等待线程池中所有的任务全部运行结束
if __name__ == '__main__':
l = []
for i in range(10):
res=pool1.submit(task, i)
l.append(res)
pool1.shutdown()
for res in l:
print('返回值:',res.result())
print('main process')
2.3 add_done_callback
–异步回调机制
回调机制相当于给每个异步提交的任务绑定了一个"炸弹",一旦这个异步提交的任务运行到返回结果的时候,就会立刻"爆炸"
from concurrent.futures import ProcessPoolExecutor
import time
pool1 = ProcessPoolExecutor(5)
def task(n):
print('--调用函数:',n)
time.sleep(0.5)
return n ** 2
def call_back(feature):
print('!!获得函数结果:',feature.result())
if __name__ == '__main__':
for i in range(10):
res = pool1.submit(task, i)
time.sleep(0.2)
res.add_done_callback(call_back)
注意:对于
add_done_callback( callback )
传入的函数名callback
,在定义callback
函数的时候一定要写一个位置参数这个位置参数会通过
add_done_callback( callback )
方法自动传入, 而且这个参数就是 调用add_done_callback
方法的feature
对象
2.4 ThreadPoolExecutor
类–线程池的开启
方法与属性 与进程池完全一致!!!