1.概述
当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程
但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到mutiprocessing模块提供的Pool方法
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求,但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行
2.使用进程池(非阻塞式)
#! /usr/bin/env python # -*- coding:utf-8 -*- import os from multiprocessing import Process, Pool from random import random import time def task(task_name): print('开始做任务', task_name) start = time.time() # 使用sleep time.sleep(random()*2) end = time.time() print('完成任务:{}!用时:{},进程id:{}'.format(task_name, (end-start), os.getpid())) if __name__ == '__main__': pool = Pool(5) tasks = ['听音乐', '吃饭', '洗衣服', '打游戏', '散步', '看孩子', '做饭'] for task1 in tasks: pool.apply_async(task, args=(task1,)) # 维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去 pool.close() pool.join() # 调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束 print('over!')
函数解释:
- apply_async(func[, args[, kwds[, callback]]]) 它是非阻塞,apply(func[, args[, kwds]])是阻塞的
- close() 关闭pool,使其不在接受新的任务。
- terminate() 结束工作进程,不在处理未完成的任务。
- join() 主进程阻塞,等待子进程的退出, join方法要在close或terminate之后使用。
执行说明:
创建一个进程池,并制定进程的数量为5,遍历,有7个任务提交到pool中,但是因为pool指定进程数为3,所以前5个被直接送到进程中执行,当其中一个执行完成后,才空出一个进程处理新的任务:看孩子。因为为非阻塞,主函数会自己执行自个的,不搭理进程的执行。
3.加入回调方法
什么是回调方法?
1.任务完成之后调用的方法
2.回调方法要有参数
import os from multiprocessing import Process, Pool from random import random import time def task(task_name): print('开始做任务', task_name) start = time.time() # 使用sleep time.sleep(random()*2) end = time.time() return '完成任务:{}!用时:{},进程id:{}'.format(task_name, (end-start), os.getpid()) container = [] def callback_func(n): container.append(n) if __name__ == '__main__': pool = Pool(5) tasks = ['听音乐', '吃饭', '洗衣服', '打游戏', '散步', '看孩子', '做饭'] for task1 in tasks: pool.apply_async(task, args=(task1,), callback=callback_func) # 维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去 pool.close() pool.join() # 调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束 for c in container: print(c) print('over!')
进程池的好处:
1.可以设置进程的数量
2.可以进程复用(一个进程执行完任务后,可以接着执行下个任务)
非阻塞的特点:全部添加到队列中,立刻返回,并没有等待其他的进程执行完毕(如把听音乐添加进去之后,并不是等听音乐这个任务执行完成之后,再添加下一个任务,而是,添加完之后,再去添加下一个任务,直到进程池满了),但是回调函数是等待任务完成之后才去调用的。