python的multiprocessing有两种建立进程的方式,每种建立方式和进程资源的回收都不太相同,下面分别针对Process,Pool及系统自带的fork三种进程分析。html
1.方式一:fork()python
举例:
linux
1 import os 2 pid = os.fork() # 建立一个子进程
3 os.wait() # 等待子进程结束释放资源
4 pid为0的表明子进程。
缺点:
1.兼容性差,只能在类linux系统下使用,windows系统不可以使用;
2.扩展性差,当须要多条进程的时候,进程管理变得很复杂;
3.会产生“孤儿”进程和“僵尸”进程,须要手动回收资源。
优势:
是系统自带的接近低层的建立方式,运行效率高。windows
2.方式二:Process进程
举例:app
1 import multiprocessing as ms 2 def test(): 3 pass
4 p1 = ms.Process(target=test) # 建立子进程
5 p1.start() # 子进程 开始执行
6 p1.join() # 等待子进程结束
特色:
1.注意:Process对象能够建立进程,但Process对象不是进程,其删除与否与系统资源是否被回收没有直接的关系。
2.主进程执行完毕后会默认等待子进程结束后回收资源,不须要手动回收资源;join()函数用来控制子进程
结束的顺序,其内部也有一个清除僵尸进程的函数,能够回收资源;
3.Process进程建立时,子进程会将主进程的Process对象彻底复制一份,这样在主进程和子进程各有一个Process
对象,可是p1.start()启动的是子进程,主进程中的Process对象做为一个静态对象存在,不执行。
4.当子进程执行完毕后,会产生一个僵尸进程,其会被join函数回收,或者再有一条进程开启,start函数也会回收
僵尸进程,因此不必定须要写join函数。
5.windows系统在子进程结束后会当即自动清除子进程的Process对象,而linux系统子进程的Process对象
若是没有join函数和start函数的话会在主进程结束后统一清除。async
另外还能够经过继承Process对象来重写run方法建立进程,这里再也不赘述。函数
3.进程池Pool:spa
1 import mutiprocessing as ms 2 def test(): 3 pass
4 p1 = Pool(5) # 建立5条进程
5 for i in range(10): 6 p1.apply_async(test) # 向进程池添加任务
7 p1.close() # 关闭进程池,再也不接受请求
8 po.join() # 等待全部的子进程结束
9 while Ture: 10 pass
分析:
1.如上,进程池Pool被建立出来后,即便实际须要建立的进程数远远大于进程池的最大上限,p1.apply_async(test)代码
依旧会不停的执行,并不会停下等待;至关于向进程池提交了10个请求,会被放到一个队列中;
2.可是有一点很重要,当执行完p1 = Pool(5)这条代码后,5条进程已经被建立出来了,只是尚未为他们各自
分配任务,也就是说,不管有多少任务,实际的进程数只有5条,计算机每次最多5条进程并行。线程
3.当Pool中有进程任务执行完毕后,这条进程资源会被释放,pool会按先进先出的原则取出一个新的请求给空闲的
进程继续执行;
4.当Pool全部的进程任务完成后,会产生5个僵尸进程,若是主线程不结束,系统不会自动回收资源,须要调用join函数去回收。
5.建立Pool池时,若是不指定进程最大数量,默认建立的进程数为系统的内核数量.code
另外还有一种阻塞式添加任务的方法,p1.apply(test),其每次只能向进程池添加一条任务,而后for循环会被堵塞等待,
直到添加的任务被执行完毕,进程池中的5个进程交替执行新来的任务,至关于单进程了。