当需要创建子进程数量不多的时候,可以直接利用multiprocessing中的Process动态生成多个进程
但是如果是成百甚至上千个任务,手动地创建它的工作量很大,此时就可以利用到multiprocessing下的pool
初始化Pool时,可以指定一个最大的进程数,当有新的请求提交到Pool中时,
如果池子还没有满,那么就会创建一个新的进程来执行该请求,但如果满了(池子中的进程已经到达最大数量)
那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行。
1 from multiprocessing import Pool 2 import os,time,random 3 4 #定义一个函数 5 def download(i): 6 print("(%d)--进程ID为%d的进程开始执行"%(i,os.getpid())) 7 t_start = time.time() 8 9 time.sleep(2* random.random()) 10 t_stop = time.time() 11 print("(%d)--进程ID为%d的进程执行完毕,耗时%f秒"%(i,os.getpid(),t_stop-t_start)) 12 13 14 15 if __name__ == '__main__': 16 po = Pool(3) #定义一个进程池,最大进程数量 17 for i in range(10): 18 #同步(自加阻塞) 19 po.apply(func=download,args=(i,)) #同步 20 21 22 # 每次循环将会用空闲出来的子进程去调用目标--异步 23 # po.apply_async(func=download,args=(i,)) #异步 24 25 print('-------start---------') 26 27 po.close() #关闭进程池,关闭后po就不再接受新的请求 28 po.join() #等待进程池中所有子进程执行完成,阻塞必须放在close之后 29 print('-------end---------')
-------start--------- (0)--进程ID为6476的进程开始执行 (1)--进程ID为6212的进程开始执行 (2)--进程ID为6284的进程开始执行 (0)--进程ID为6476的进程执行完毕,耗时0.975056秒 (3)--进程ID为6476的进程开始执行 (1)--进程ID为6212的进程执行完毕,耗时1.030059秒 (4)--进程ID为6212的进程开始执行 (2)--进程ID为6284的进程执行完毕,耗时1.735099秒 (5)--进程ID为6284的进程开始执行 (4)--进程ID为6212的进程执行完毕,耗时1.078062秒 (6)--进程ID为6212的进程开始执行 (6)--进程ID为6212的进程执行完毕,耗时0.373021秒 (7)--进程ID为6212的进程开始执行 (3)--进程ID为6476的进程执行完毕,耗时1.759101秒 (8)--进程ID为6476的进程开始执行 (5)--进程ID为6284的进程执行完毕,耗时1.608092秒 (9)--进程ID为6284的进程开始执行 (9)--进程ID为6284的进程执行完毕,耗时0.325019秒 (7)--进程ID为6212的进程执行完毕,耗时1.248071秒 (8)--进程ID为6476的进程执行完毕,耗时1.817104秒 -------end---------
* 刚开始有3个进程,执行完一个之后,后面的新进程添加进来,依次类推。谁先运行完,不一定。
* 这里`po.join()`阻塞程序执行,主进程和子进程都用print。如果没有,会看不到效果。
1 from multiprocessing import Pool 2 import os,time,random 3 4 #定义一个函数 5 def download(i): 6 print("(%d)--进程ID为%d的进程开始执行"%(i,os.getpid())) 7 t_start = time.time() 8 9 time.sleep(2* random.random()) 10 t_stop = time.time() 11 print("(%d)--进程ID为%d的进程执行完毕,耗时%f秒"%(i,os.getpid(),t_stop-t_start)) 12 13 14 15 if __name__ == '__main__': 16 po = Pool(3) #定义一个进程池,最大进程数量 17 for i in range(10): 18 #同步(自加阻塞) 19 # po.apply(func=download,args=(i,)) #同步 20 21 22 # 每次循环将会用空闲出来的子进程去调用目标--异步 23 po.apply_async(func=download,args=(i,)) #异步 24 25 print('-------start---------') 26 27 po.close() #关闭进程池,关闭后po就不再接受新的请求 28 po.join() #等待进程池中所有子进程执行完成,阻塞必须放在close之后 29 print('-------end---------')
#同步时,输出的结果: (0)--进程ID为5648的进程开始执行 (0)--进程ID为5648的进程执行完毕,耗时0.069004秒 (1)--进程ID为2556的进程开始执行 (1)--进程ID为2556的进程执行完毕,耗时1.278073秒 (2)--进程ID为1864的进程开始执行 (2)--进程ID为1864的进程执行完毕,耗时1.308075秒 (3)--进程ID为5648的进程开始执行 (3)--进程ID为5648的进程执行完毕,耗时1.673096秒 (4)--进程ID为2556的进程开始执行 (4)--进程ID为2556的进程执行完毕,耗时0.887051秒 (5)--进程ID为1864的进程开始执行 (5)--进程ID为1864的进程执行完毕,耗时1.699097秒 (6)--进程ID为5648的进程开始执行 (6)--进程ID为5648的进程执行完毕,耗时1.817104秒 (7)--进程ID为2556的进程开始执行 (7)--进程ID为2556的进程执行完毕,耗时0.595034秒 (8)--进程ID为1864的进程开始执行 (8)--进程ID为1864的进程执行完毕,耗时0.231013秒 (9)--进程ID为5648的进程开始执行 (9)--进程ID为5648的进程执行完毕,耗时1.656095秒 -------start--------- -------end---------
同步和异步的区别: