Process对象的其它方法与属性(join)
一 Process对象的join方法
在主进程运行过程中如果想并发地执行其他的任务,我们可以开启子进程,此时主进程的任务与子进程的任务分两种情况
情况一:在主进程的任务与子进程的任务彼此独立的情况下,主进程的任务先执行完毕后,主进程还需要等待子进程执行完毕,然后统一回收资源。
情况二:如果主进程的任务在执行到某一个阶段时,需要等待子进程执行完毕后才能继续执行,就需要有一种机制能够让主进程检测子进程是否运行完毕,在子进程执行完毕后才继续执行,否则一直在原地阻塞,这就是join方法的作用
# join方法 from multiprocessing import Process import time import os def task(name): # os.getppid()查看父进程编号 print("%s is running, parent id is <%s>" % (os.getpid(), os.getppid())) # os.getpid()查看自己进程编号 time.sleep(3) # 模拟任务运行一段时间 print("%s is done, parent id is <%s>" % (os.getpid(), os.getppid())) if __name__ == "__main__": # windows 一定要把开启指令放到main下面 Linux无所谓 # Process(target=task, kargs={"name" : "子进程"}) # 方式1 p = Process(target=task, args=("子进程1",)) # 方式2 实例化得到一个对象 p.start() # (仅仅只是给操作系统发送了一个信号)开启子进程,帮你执行task p.join() # 主进程会等子进程运行(主进程基于子进程执行的结果进行后续代码的执行) print("主", os.getpid(), os.getppid()) # 此时的父进程是pycharm print(p.pid) # p对象下的pid(验证僵尸进程)
10952 is running, parent id is <8624>
10952 is done, parent id is <8624>
主 8624 124
10952
from multiprocessing import Process import time import os def task(name, n): # os.getppid()查看父进程编号 print("%s is running" % name) # os.getpid()查看自己进程编号 time.sleep(n) # 模拟任务运行一段时间 if __name__ == "__main__": # windows 一定要把开启指令放到main下面 Linux无所谓 start = time.time() p1 = Process(target=task, args=("子进程1", 5)) p2 = Process(target=task, args=("子进程2", 3)) p3 = Process(target=task, args=("子进程3", 2)) p_l = [p1, p2, p3] # p1.start() # (仅仅只是给操作系统发送了一个信号)开启子进程,帮你执行task(不一定按顺序) # p2.start() # p3.start() for i in p_l: # 简写 i.start() # p1.join() # 让主进程等,连续三个并发执行 # p2.join() # p3.join() for p in p_l: p.join() print("主", (time.time()-start)) # 此时的父进程是pycharm
子进程1 is running
子进程2 is running
子进程3 is running
主 5.103978633880615
注意:
进程只要start就会在开始运行了,所以p1-p3.start()时,系统中已经有并发的进程了
join是让主线程等,而p1-p3仍然是并发执行的,p1.join的时候,其余p2,p3,p4仍然在运行,等#p1.join结束,可能p2,p3早已经结束了,这样p2.join,p3.join直接通过检测,无需等待
所以3个join花费的总时间仍然是耗费时间最长的那个进程运行的时间
串行
# 串联执行 from multiprocessing import Process import time import os def task(name, n): # os.getppid()查看父进程编号 print("%s is running" % name) # os.getpid()查看自己进程编号 time.sleep(n) # 模拟任务运行一段时间 if __name__ == "__main__": # windows 一定要把开启指令放到main下面 Linux无所谓 start = time.time() p1 = Process(target=task, args=("子进程1", 5)) p2 = Process(target=task, args=("子进程2", 3)) p3 = Process(target=task, args=("子进程3", 2)) p1.start() # (仅仅只是给操作系统发送了一个信号)开启子进程,帮你执行task(不一定按顺序) p1.join() # 主程序再等P1 p2.start() # p2 才开始 p2.join() p3.start() p3.join() print("主", (time.time()-start)) # 此时的父进程是pycharm
子进程1 is running
子进程2 is running
子进程3 is running
主 10.3139066696167
二 Process对象的其他属性或方法
进程对象的其他方法一:is_alive
# 了解 p.is_alive() from multiprocessing import Process import time import os def task(name): # os.getppid()查看父进程编号 print("%s is running, parent id is <%s>" % (os.getpid(), os.getppid())) # os.getpid()查看自己进程编号 time.sleep(3) # 模拟任务运行一段时间 print("%s is done, parent id is <%s>" % (os.getpid(), os.getppid())) if __name__ == "__main__": # windows 一定要把开启指令放到main下面 Linux无所谓 # Process(target=task, kargs={"name" : "子进程"}) # 方式1 p = Process(target=task, args=("子进程1",)) # 方式2 实例化得到一个对象 p.start() # (仅仅只是给操作系统发送了一个信号)开启子进程,帮你执行task print(p.is_alive()) # 判断活着还是死的 p.join() # 主进程会等子进程运行(主进程基于子进程执行的结果进行后续代码的执行) print("主", os.getpid(), os.getppid()) # 此时的父进程是pycharm print(p.pid) # p对象下的pid(验证僵尸进程) print(p.is_alive()) # 判断活着还是死的
进程对象的其他属性:terminal
# 了解 p.terminate() from multiprocessing import Process import time import os def task(name): # os.getppid()查看父进程编号 print("%s is running, parent id is <%s>" % (os.getpid(), os.getppid())) # os.getpid()查看自己进程编号 time.sleep(3) # 模拟任务运行一段时间 print("%s is done, parent id is <%s>" % (os.getpid(), os.getppid())) if __name__ == "__main__": # windows 一定要把开启指令放到main下面 Linux无所谓 # Process(target=task, kargs={"name" : "子进程"}) # 方式1 p = Process(target=task, args=("子进程1",)) # 方式2 实例化得到一个对象 p.start() # (仅仅只是给操作系统发送了一个信号)开启子进程,帮你执行task print("主") p.terminate() # 给操作系统发出信号终止进程 time.sleep(3) print(p.is_alive())
进程对象的其他属性:name
# 了解 p.name from multiprocessing import Process import time import os def task(name): # os.getppid()查看父进程编号 print("%s is running, parent id is <%s>" % (os.getpid(), os.getppid())) # os.getpid()查看自己进程编号 time.sleep(3) # 模拟任务运行一段时间 print("%s is done, parent id is <%s>" % (os.getpid(), os.getppid())) if __name__ == "__main__": # windows 一定要把开启指令放到main下面 Linux无所谓 # Process(target=task, kargs={"name" : "子进程"}) # 方式1 p = Process(target=task, args=("子进程1",), name="我的进程") # 方式2 实例化得到一个对象 p.start() # (仅仅只是给操作系统发送了一个信号)开启子进程,帮你执行task print("主") print(p.name) # 查看进程名称(默认为Process-1)
三 练习题
1、改写下列程序,分别别实现下述打印效果
from multiprocessing import Process
import time
import random
def task(n):
time.sleep(random.randint(1,3))
print('-------->%s' %n)
if __name__ == '__main__':
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,))
p1.start()
p2.start()
p3.start()
print('-------->4')
效果一:保证最先输出-------->4
-------->4
-------->1
-------->3
-------->2
from multiprocessing import Process import time import random def task(n): time.sleep(random.randint(1, 3)) print('-------->%s' % n) if __name__ == '__main__': p1 = Process(target=task, args=(1,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(3,)) p_1 = [p1, p2, p3] for p in p_1: p.start() print('-------->4')
效果二:保证最后输出-------->4
-------->2
-------->3
-------->1
-------->4
from multiprocessing import Process import time import random def task(n): time.sleep(random.randint(1, 3)) print('-------->%s' % n) if __name__ == '__main__': p1 = Process(target=task, args=(1,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(3,)) p_1 = [p1, p2, p3] for p in p_1: p.start() for p in p_1: p.join() print('-------->4')
效果三:保证按顺序输出
-------->1
-------->2
-------->3
-------->4
from multiprocessing import Process import time import random def task(n): time.sleep(random.randint(1, 3)) print('-------->%s' % n) if __name__ == '__main__': p1 = Process(target=task, args=(1,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(3,)) p_1 = [p1, p2, p3] for p in p_1: p.start() p.join() print('-------->4')
2、判断上述三种效果,哪种属于并发,哪种属于串行?
answer
效果一与效果二,是并发,效果三是串行