2.如果主进程的任务在执行到某一阶段后,需要等待子进程执行完毕后才能继续执行,就需要有一种机制能够让主进程检测子进程进程是否运行完毕,在子进程执行完毕后才继续执行,否则一直在原地阻塞,这就是join方法的作用。
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super().__init__()
self.name = name
def run(self):
print('%s is running.'%self.name)
time.sleep(2)
print('%s is done.'%self.name)
if __name__ == '__main__': # windows系统需要在main下开启进程
p = MyProcess('子进程') # 实例化子进程
p.start() # 给操作系统发送信号,把父进程的数据拷贝给子进程作为初始数据
p.join() # join方法,等到子进程完成之后,才会执行主进程
print('主进程')
# 运行结果如下:
子进程 is running.
子进程 is done.
主进程
有的人可能会问了,有了join()方法的话,程序不就变成串行了吗?在这里解释一下:
进程只要start就会在开始运行了,所以p.start()时,系统中已经有了1个并发的进程了,而我们p.join()是在等p结束,没错p只要不结束主线程就不会执行,这也是问题的关键,join是让主线程在等,而p或者以后的p1/p2/p3仍然是并发执行的,等到p.join()结束,可能p1/p2/p3早都结束了,这样的话,p1/p2/p3就忽略了检测,无需等待。
所以不管有多少个join()方法,需要等到的时候仍然是耗费时间最长的那个进程运行的时间。
terminate和is_alive方法
其中is_alive()是检测进程是否存活,而terminate方法是用来关闭进程的,当然不会立马关闭
# is_alive()检测进程是否存活
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super(MyProcess, self).__init__()
self.name = name
def run(self):
print('%s is running'%self.name)
time.sleep(3)
print('%s is done'%self.name)
if __name__ == '__main__':
p1 = MyProcess('子进程1')
p1.start()
print('子进程进程是否存活:',p1.is_alive())
p1.join()
print('主进程')
print('第二次检测是否存活:',p1.is_alive())
# 运行结果为
子进程进程是否存活: True
子进程1 is running
子进程1 is done
主进程
第二次检测是否存活: False
这是由于主进程完成了任务,所以子进程就跟着主进程一起死掉了。
# terminate杀死进程,不会立马杀死掉
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super(MyProcess, self).__init__()
self.name = name
def run(self):
print('%s is running'%self.name)
time.sleep(3)
print('%s is done'%self.name)
if __name__ == '__main__':
p1 = MyProcess('子进程1')
p1.start()
p1.terminate() # 杀死子进程1
print('第一次检测子进程进程是否存活:',p1.is_alive())
p1.join()
print('主进程')
print('第二次检测是否存活:',p1.is_alive())
运行结果为:
第一次检测子进程进程是否存活: True
主进程
第二次检测是否存活: False
在p1子进程刚刚把信号传递给操作系统之后,就利用了terminate方法杀死了子进程1,但是不是立马杀死,所以此时的p1子进程还是属于存活状态,等到打印完'主进程'之后,p1就跟随着主进程死掉了,所以此时子进程存活状态为False。
name和pid方法
其中,查看当前进程PID为os.getpid()方法,os.getppid()为查看父进程的PID方法
pid方法刚刚已经说过了,所以就不举例了
# name方法
from multiprocessing import Process
import time
def task(name):
print('%s is running'%name)
time.sleep(2)
print('%s is done'%name)
if __name__ == '__main__':
p1 = Process(target=task,args=('xiao',))
p1.start()
p1.join()
print(p1.name) # 打印子进程的进程名
print('主进程')
# 运行结果为:
xiao is running
xiao is done
Process-1 # 子进程的进程名,默认的,可以修改
主进程
# 如果想要修改进程名,只需要在实例化的时候添加name属性就可以了,具体操作为:
p1 = Process(target=task,args=('xiao',),name='子进程1')
守护进程
主进程设置进程,然后将该进程设置成自己的守护进程。
关于守护进程需要强调两点:
1.守护进程会跟随者主进程代码执行结束后终止
2.守护进程内无法再开启子进程,否则会抛出异常