python中进程池的应用
简介:
假设我们写的一个程序需要运行100个子进程的时候,那么写程序时,不可能循环创建销毁100个进程吧?进程的创建与销毁是很耗系统的资源的。
进程池的作用就体现出来了,进程池可以控制进程的数量,重复利用进程对象,减少创建和销毁进程的开销。
1.创建进程池
pool = multiprocessing.Pool(5) #指定有几个子进程在“同时”进行(为什么说是“同时”,因为在并发的情况下,子进程和主进程是按照时间片轮寻的方式执行的,只是切换得过快,并不是真的一起运行。)
Pool可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。
2.进程池的应用
import multiprocessing import os import random import time def run_time(index): start_time = time.time() time.sleep(random.random()) print("任务%d 任务id为%d 任务运行的时间为%0.2f" % (index,os.getpid(), time.time()-start_time)) if __name__ == '__main__': pool = multiprocessing.Pool(3)#指定同时进程数
#for表示需要创建多少进程 for i in range(10): pool.apply_async(func=run_time,args=(i,)) pool.close()#关闭当前进程对象 pool.join()#等待全部经常执行完成 print("结束标志") 输出: 任务2 任务id为3191 任务运行的时间为0.29 任务1 任务id为3190 任务运行的时间为0.33 任务0 任务id为3189 任务运行的时间为0.45 任务3 任务id为3191 任务运行的时间为0.41 任务4 任务id为3190 任务运行的时间为0.39 任务5 任务id为3189 任务运行的时间为0.76 任务7 任务id为3190 任务运行的时间为0.52 任务6 任务id为3191 任务运行的时间为0.80 任务8 任务id为3189 任务运行的时间为0.56 任务9 任务id为3190 任务运行的时间为0.80 结束标志
3.进程池的进程默认都是守护进程
进程池的子进程都是由主进程创建的,且默认都是守护进程。所以当主进程执行完之后,进程池的子进程全部都被中断。如果需要执行完进程池的子进程,才结束程序,需要加上两句代码。
pool.close() # 必须先关闭进程池,不再让它接收新的进程,才能进行下一步的阻塞。(已经在排队的进程不算新进程了!例如上面的例子,
10个子进程已经在进程池排队,所以join方法会阻塞直到10个子进程执行完成。) pool.join()
上面的例子,如果没有这两句代码,输出会变成下面的结果
import multiprocessing import os import random import time def run_time(index): start_time = time.time() time.sleep(random.random()) print("任务%d 任务id为%d 任务运行的时间为%0.2f" % (index,os.getpid(), time.time()-start_time)) if __name__ == '__main__': pool = multiprocessing.Pool(3) for i in range(10): pool.apply_async(func=run_time,args=(i,)) print("结束标志") 输出: 结束标志
进程池排队的10个进程,都是守护进程。还没来得及运行,主进程运行了,然后中断了进程池所有的子进程,因次子进程并没有输出。
4.进程池中子进程之间的通信。
关于进程间的通信,可以看我的另一篇博客。https://www.cnblogs.com/chichung/p/9533227.html
那么,进程池中的子进程之间怎么进行通信呢?
我们来在进程池创建两个子进程,然后让一个子进程把数据放在队列,另外一个子进程在队列里取数据。
import multiprocessing import time def send_data(queue): for i in "python": queue.put(i) print("把%s放进队列里" % i) def recv_data(queue): while not queue.empty(): data = queue.get() print("在队列里取得%s" % data) if __name__ == '__main__': q = multiprocessing.Manager().Queue(5) # 进程池之间的通信中间要加Manager(),单纯进程间的通信并不用,这是最大的区别。 pool = multiprocessing.Pool(2) pool.apply_async(func=send_data,args=(q,)) time.sleep(1) pool.apply_async(func=recv_data,args=(q,)) time.sleep(1) pool.close() pool.join() print("结束标志") 输出: 把p放进队列里 把y放进队列里 把t放进队列里 把h放进队列里 把o放进队列里 在队列里取得p 把n放进队列里 在队列里取得y 在队列里取得t 在队列里取得h 在队列里取得o 在队列里取得n 结束标志
相关连接:
https://www.cnblogs.com/zingp/p/5911537.html ......................Python中的协程
https://www.cnblogs.com/nanyu/p/11668767.html .............协程示例
浙公网安备 33010602011771号