使用进程池的原因
由于每一次开启进程,需要系统为其开辟属于这个进程的内存空间以及一系列寄存器、堆栈、文件的分配,关闭一个进程的时候也有一系列回收的操作。
因此每一次使用多进程批量执行任务,是很消耗系统资源,并且降低效率的。
因此就有了进程池的概念,系统会预先创建一定数量的进程,每当有任务来的时候,就会使用已经创建的进程来运行任务代码,任务结束之后也不会释放,因此大大减少了进程创建和回收的时候的资源损耗,提高了代码运行的效率
进程池的基础使用
from multiprocessing import Pool
def func1(name):
print("%s is coming"%name)
if __name__ == '__main__':
pool = Pool(5) #创建5个进程的进程池
pool.map(func1,["sun","moon","star"])
---------------------
sun is coming
moon is coming
star is coming
pool.map方法就是传入一个函数和可迭代的参数,可迭代的参数会依次传入函数的参数中
同步执行任务
pool中的apply方法可以同步执行待执行的任务代码
from multiprocessing import Pool
from time import sleep
def func1(name):
print("%s is up"%name)
sleep(1)
print("%s is down" %name)
if __name__ == '__main__':
pool = Pool(5)
for i in ["sun","moon","star"]:
pool.apply(func1,args=(i,))
-------------------------
sun is up
sun is down
moon is up
moon is down
star is up
star is down
异步执行任务
from multiprocessing import Pool
from time import sleep
def func1(name):
print("%s is up"%name)
sleep(1)
print("%s is down" %name)
if __name__ == '__main__':
pool = Pool(5)
for i in ["sun","moon","star"]:
pool.apply_async(func1,args=(i,))
pool.close() #感知到进程池中的任务已经执行完毕
pool.join() #主进程随着子进程的任务执行完毕而结束
---------------------------------------
sun is up
moon is up
star is up
star is down
sun is down
moon is down
和同步执行不同的是,主进程不会等待子进程的结束而结束,因此如果不加close和join看不到任何子进程中执行的输出,而单加join也不行,因为进程池中的进程不会释放,也没有结束一说,所以单加join会报错。
进程值的返回
from multiprocessing import Pool
from time import sleep
def func1(i):
return i*i
if __name__ == '__main__':
pool = Pool(5)
res_l = []
for i in range(10):
res = pool.apply_async(func1,args=(i,))
res_l.append(res)
for res in res_l:print(res.get())
这个例子为何要采用列表的形式,收集结果后再打印呢
因为这样能提高程序运行的效率,因为res.get要等子进程运行完才能取到结果,因此会产生堵塞,我们如果把结果都添加到列表中,一次性打印就可以最大效用的利用异步执行的优势。