一 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

效果一与效果二,是并发,效果三是串行