(一)简介
为什么要有进程池?进程池的概念。
在程序实际处理问题过程中,忙时会有成千上万的任务需要被执行,闲时可能只有零星任务。那么在成千上万个任务需要被执行的时候,我们就需要去创建成千上万个进程么?首先,创建进程需要消耗时间,销毁进程也需要消耗时间。第二即便开启了成千上万的进程,操作系统也不能让他们同时执行,这样反而会影响程序的效率。因此我们不能无限制的根据任务开启或者结束进程。那么我们要怎么做呢?
在这里,要给大家介绍一个进程池的概念,定义一个池子,在里面放上固定数量的进程,有需求来了,就拿一个池中的进程来处理任务,等到处理完毕,进程并不关闭,而是将进程再放回进程池中继续等待任务。如果有很多任务需要执行,池中的进程数量不够,任务就要等待之前的进程执行任务完毕归来,拿到空闲进程才能继续执行。也就是说,池中进程的数量是固定的,那么同一时间最多有固定数量的进程在运行。这样不会增加操作系统的调度难度,还节省了开闭进程的时间,也一定程度上能够实现并发效果。
(二)语法格式
我们通过下面的一个简单实例来了解创建进程池的基本方法:
1 import time 2 from multiprocessing import Pool 3 def fc(i): 4 time.sleep(0.5) 5 print('func%s'%i) 6 7 if __name__ == '__main__': 8 p = Pool(5) 9 for i in range(5): 10 11 p.apply(func=fc,args=(i,)) # 同步调用 12 或者 13 p.apply_async(func=fc, args=(1,)) # 异步调用
(三)同步调用和异步调用的区别:
通过上面的语法格式,我们可以看出,存在同步和异步调用:
同步调用:直到本次任务执行完毕时,才加入下一个任务,等待本次任务执行的过程中可能有阻塞也可能没有阻塞,但不管该任务是否存在阻塞,同步调用都会在原地等着。
看如下例子:
1 from multiprocessing import Pool 2 import random 3 import os 4 import time 5 6 7 def f(i): 8 time_start = time.time() 9 print("---进程%d运行中,pid=%d---"% (i, os.getpid())) 10 time.sleep(random.randint(1,4)) 11 time_stop = time.time() 12 print('进程%d耗时%0.5f'% (i, (time_stop-time_start))) 13 14 15 if __name__ == '__main__': 16 po = Pool(3) 17 for i in range(10): 18 po.apply(func=f, args=(i,)) 19 20 print("----start----") 21 print('----stop----') 22 23 》》》输出: 24 ---进程0运行中,pid=10244--- 25 进程0耗时3.00086 26 ---进程1运行中,pid=8140--- 27 进程1耗时2.00089 28 ---进程2运行中,pid=27480--- 29 进程2耗时3.00057 30 ---进程3运行中,pid=10244--- 31 进程3耗时2.00040 32 ---进程4运行中,pid=8140--- 33 进程4耗时1.00129 34 ---进程5运行中,pid=27480--- 35 进程5耗时1.00084 36 ---进程6运行中,pid=10244--- 37 进程6耗时2.00106 38 ---进程7运行中,pid=8140--- 39 进程7耗时2.00045 40 ---进程8运行中,pid=27480--- 41 进程8耗时3.00015 42 ---进程9运行中,pid=10244--- 43 进程9耗时3.00059 44 ----start---- 45 ----stop----
可以看到,如果任务有返回值,那么会一个一个的返回。
异步调用:根据进程池中有的进程数,每次最多三个子进程在异步执行,每次执行完一个就释放一个进程,这个进程就去接收新的任务。所以如果使用异步提交任务,主进程需要使用join,等待进程池内的任务处理完,否则,主进程结束,进程池可能还没有来得及执行,就跟着一起结束了。
看如下实例:
1 from multiprocessing import Pool 2 import random 3 import os 4 import time 5 6 7 def f(i): 8 time_start = time.time() 9 print("---进程%d运行中,pid=%d---"% (i, os.getpid())) 10 time.sleep(random.randint(1,4)) 11 time_stop = time.time() 12 print('进程%d耗时%0.5f'% (i, (time_stop-time_start))) 13 14 15 if __name__ == '__main__': 16 po = Pool(3) 17 for i in range(10): 18 po.apply_async(func=f, args=(i,)) 19 20 print("----start----") 21 po.close() 22 po.join() 23 print('----stop----') 24 25 26 》》》输出: 27 ----start---- 28 ---进程0运行中,pid=9608--- 29 ---进程1运行中,pid=4644--- 30 ---进程2运行中,pid=19992--- 31 进程1耗时1.00100 32 ---进程3运行中,pid=4644--- 33 进程3耗时1.00022 34 ---进程4运行中,pid=4644--- 35 进程0耗时3.00073 36 ---进程5运行中,pid=9608--- 37 进程2耗时3.00091 38 ---进程6运行中,pid=19992--- 39 进程5耗时2.00013 40 ---进程7运行中,pid=9608--- 41 进程4耗时3.00048 42 ---进程8运行中,pid=4644--- 43 进程7耗时1.00039 44 ---进程9运行中,pid=9608--- 45 进程8耗时1.00056 46 进程6耗时4.00056 47 进程9耗时3.00023 48 ----stop----