python并发编程 Process对象的其他属性方法join方法详解
作者:minger_lcm 发布时间:2022-03-07 04:29:54
一 Process对象的join方法
在主进程运行过程中如果想并发地执行其他的任务,我们可以开启子进程,此时主进程的任务与子进程的任务分两种情况
情况一:
在主进程的任务与子进程的任务彼此独立的情况下,主进程的任务先执行完毕后,主进程还需要等待子进程执行完毕,然后统一回收资源。 这种是没有join方法
情况二:
如果主进程的任务在执行到某一个阶段时,需要等待子进程执行完毕后才能继续执行,
就需要有一种机制能够让主进程检测子进程是否运行完毕,在子进程执行完毕后才继续执行,否则一直在原地阻塞,这就是join方法的作用
让主进程等着,所有子进程执行完毕后,主进程才继续执行
from multiprocessing import Process
import time
import os
def task():
print("%s is running,parent id is <%s>" % (os.getpid(), os.getppid()))
time.sleep(3)
print("%s is done,parent id is <%s>" % (os.getpid(), os.getppid()))
if __name__ == "__main__":
t = Process(target=task, )
t.start()
t.join()
# 主进程 等子进程执行完了
print("主", os.getpid(), os.getppid())
'''
is running,parent id is <25956>
is done,parent id is <25956>
主 25956 2992
'''
子进程运行完,最后打印主进程,主进程结束了 所有僵尸进程都会回收
开启多个字进程 向操作系统发送信号,但操作系统要处理的任务太多了,先开启 哪个子进程是随机的,有时候可能先开启主进程先,
操作系统什么时候开,开多长时间,我们是不知道的
from multiprocessing import Process
import time
import os
def task(name):
print('%s is running' %name)
time.sleep(2)
print('%s is end' %name)
if __name__ == '__main__':
p1 = Process(target=task, args=('子进程1',))
p2 = Process(target=task, args=('子进程2',))
p3 = Process(target=task, args=('子进程3',))
p4 = Process(target=task, args=('子进程4',))
p1.start()
p2.start()
p3.start()
p4.start()
print('主',os.getpid(),os.getppid())
'''
子进程1 is running
子进程2 is running
主 9268 5236
子进程3 is running
子进程4 is running
子进程1 is end
子进程2 is end
子进程3 is end
子进程4 is end
'''
也有可能这样,先开启主进程,
主 9556 5236
子进程1 is running
子进程3 is running
子进程2 is running
子进程4 is running
子进程1 is end
子进程3 is end
子进程2 is end
子进程4 is end
p.start() 只是给操作系统发送信号
join 会变串行?
既然join是等待进程结束, 那么我像下面这样写, 进程不就又变成串行的了吗?
当然不是了, 必须明确:p.join()是让谁等?
很明显p.join()是让主线程等待p 子进程的结束,卡住的是主进程而绝非 子进程p,
from multiprocessing import Process
import time
import os
def task(name):
print('%s is running' %(name))
time.sleep(2)
print('%s is end' %(name))
if __name__ == '__main__':
p1 = Process(target=task, args=('子进程1',))
p2 = Process(target=task, args=('子进程2',))
p3 = Process(target=task, args=('子进程3',))
p4 = Process(target=task, args=('子进程4',))
p1.start()
p2.start()
p3.start()
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
print('主',os.getpid(),os.getppid())
详细解析如下:
进程只要start就会在开始运行了,所以p1-p4.start()时,系统中已经有四个并发的进程了
而我们p1.join()是在等p1结束,没错p1只要不结束主线程就会一直卡在原地,这也是问题的关键
join是让主线程等,而p1-p4仍然是并发执行的,p1.join的时候,其余p2,p3,p4仍然在运行,等#p1.join结束,可能p2,p3,p4早已经结束了,这样p2.join,p3.join.p4.join直接通过检测,无需等待
所以4个join花费的总时间仍然是耗费时间最长的那个进程运行的时间
所以不会是串行执行,是并发执行
4个join花费的总时间仍然是耗费时间最长的那个进程运行的时间
所以就是5秒,就是子进程1 那个等待的时间
from multiprocessing import Process
import time
import os
def task(name,n):
print('%s is running' %(name))
time.sleep(n)
print('%s is end' %(name))
if __name__ == '__main__':
start = time.time()
p1 = Process(target=task, args=('子进程1',5))
p2 = Process(target=task, args=('子进程2',2))
p3 = Process(target=task, args=('子进程3',2))
p4 = Process(target=task, args=('子进程4',2))
p1.start()
p2.start()
p3.start()
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
print('主',time.time() - start)
'''
子进程1 is running
子进程2 is running
子进程3 is running
子进程4 is running
子进程2 is end
子进程3 is end
子进程4 is end
子进程1 is end
主 5.413309812545776
'''
这种方式就是串行
等子进程1执行时候,子进程2就没有发送信号,要等子进程1 执行完,再子进程2发送信号 ,开启子进程2再执行,按照这样的顺序
from multiprocessing import Process
import time
import os
def task(name,n):
print('%s is running' %(name))
time.sleep(n)
print('%s is end' %(name))
if __name__ == '__main__':
start = time.time()
p1 = Process(target=task, args=('子进程1',5))
p2 = Process(target=task, args=('子进程2',2))
p3 = Process(target=task, args=('子进程3',2))
p4 = Process(target=task, args=('子进程4',2))
p1.start()
p1.join()
p2.start()
p2.join()
p3.start()
p3.join()
p4.start()
p4.join()
print('主',time.time() - start)
'''
子进程1 is running
子进程1 is end
子进程2 is running
子进程2 is end
子进程3 is running
子进程3 is end
子进程4 is running
子进程4 is end
主 12.212698698043823
'''
上述启动进程与 join进程 可以简写为以下
from multiprocessing import Process
import time
import os
def task(name,n):
print('%s is running' %(name))
time.sleep(n)
print('%s is end' %(name))
if __name__ == '__main__':
start = time.time()
p1 = Process(target=task, args=('子进程1',5))
p2 = Process(target=task, args=('子进程2',2))
p3 = Process(target=task, args=('子进程3',2))
p4 = Process(target=task, args=('子进程4',2))
process_list = [p1,p2,p3,p4]
for p in process_list:
p.start()
for p in process_list:
p.join()
print('主',time.time() - start)
join 保证所有子进程执行完 主进程才能工作,不然一直阻塞
来源:https://www.cnblogs.com/mingerlcm/p/8987034.html
猜你喜欢
- 为了将excel数据自动转换成所需要的erlang数据,听同事说使用python会很方便简单,就自学了两天python,写了一个比较粗糙的p
- 导语大家以前应该都听说过一个游戏:叫做走四棋儿这款游戏出来到现在时间挺长了,小时候的家乡农村条件有限,附近也没有正式的玩具店能买到玩具,因此
- 前言最近在学习python 爬虫方面的知识,网上有一博客专栏专门写爬虫方面的,看到用urllib请求有道翻译接口获取翻译结果。发现接口变化很
- 本文阐述了网页设计中的十大诀窍,作为网页开发者我们应该注意,这样才能最大限度得发挥网站的功能和效益: 预早筹划设计主页未必很艰难。
- 下面是asp代码实现列出sql数据库中存储过程的功能,可自行添加其它功能:< HTML >< 
- 单线程同步使用socket传输数据使用json序列化消息体struct将消息编码为二进制字节串,进行网络传输消息协议// 输入{  
- 工作中,网页设计师经常会遇见这些状况:时间这么短又要出彩、又是要大气要有气氛、风格不明确很难把握、栏目这么多页面又这么长……突然觉得束手无策
- 实例如下所示:import matplotlib.pyplot as pltplt.imshow(img)#控制台打印出图像对象的信息,而图
- 在做我的友情链接批量检查工具过程中,碰到一些情况,就是对方网页会用gzip压缩。用gzip压缩的好处是,能压缩网页大小,加快网页的浏览速度,
- Python 中提供了对时间日期的多种多样的处理方式,主要是在 time 和 datetime 这两个模块里。一、time 模块time 模
- 前一段时间导师叫我写一个批处理的小程序,就是循环修改辐射传输模型软件MODTRAN的输入参数,然后运行MODTRAN软件进行计算,输出需要的
- 先来看个例子:需求为生成4位数,不足前面补0<?php //生成4位数,不足前面补0 $var=sprintf
- 如下所示:from pandas_datareader import data, wbfrom datetime import dateti
- 目录[redis 调用Lua脚本](#redis 调用Lua脚本)[redis+lua 实现评分排行榜实时更新](#redis+lua 实现
- 在爬虫的获取数据上,一直在讲一些爬取的方法,想必小伙伴们也学习了不少。在学习的过程中遇到了问题,大家也会一起交流解决,找出不懂和出错的地方。
- 众所周知,随着数据库体积的日益庞大,其备份文件的大小也水涨船高。虽然说通过差异备份与完全备份配套策略,可以大大的减小SQL Server数据
- 需求背景:进行分值计算。如下图,如果只是一两个还好说,写写判断,但是如果有几十个,几百个,会不会惨不忍睹。而且,下面的还是三种情况。例如:解
- IE5及其以后版本支持在CSS中使用expression,用来把CSS属性和Javascript表达式关联起来,这里的CSS属性可以是元素固
- 建立随机生成的HTML代码是一件相当容易实现的ASP特性。你可能创建过“每日一帖”、滚动广告等等,只需要稍加点缀就会令你的网站日久弥新。对存