(python) 多线程和多进程中的join方法的用处

python中为了加快任务的运行速度,会采用多线程或者多线程的方式。不论是在多进程还是多线程中都会用到join()方法,开始不知道这个方法是干什么的,因此在网上查看很多文章后总结了一下join()方法的用处。

此处不解释进程和线程的区别,但首先要知道进程是线程的容器,即一个进程可以包含很多线程。此处使用多线程作为例子进行解释。


默认情况:

每一个进程启动后都默认会产生一个主线程,在默认情况下(即setDaemon(False),默认即为False,不用设置),使用threading模块产生新的线程后,子线程和主线程的运行是独立的,即主线程停止后子线程也会继续运行直到子线程任务结束,子线程停止当然更不会影响主线程的运行。(此处使用停止来描述主进程是因为即使主线程执行完任务,但主线程还是存在于整个进程列表中,个人这样理解哈,便于后续的理解)

import threading
def test():
	x = 0
	for i in range(5):
		x = i + x
		print(x)
	print(str(threading.enumerate())) # 打印出当前进程中的所有线程

if __name__ == '__main__':
	thread = threading.Thread(target=test)
	thread.start()
	print('nihao')

结果如下

在这里插入图片描述

从结果中可以看出主线程中要打印的‘nihao’在子线程运行第一次循环即x=0+0后就已经打印出来了,此后主线程就进入停止状态(即stop状态),之后在子线程循环结束后,打印出当前所有线程。可以发现有主线程和子线程两个进程,但主线程已经停止了,即说明了默认情况下主线程停止不影响子进程的运行。(这里我理解是主线程虽然已经停止,但其需要等待子线程全部停止即结束,这样才能代表整个脚本的任务完成,这时候一个完整的进程才算结束。)

设置守护进程的情况:

若将setDaemon设置为True时则与默认情况不一样,setDaemon的意思是设置某线程为守护线程。守护线程很多人解释说是当主进程结束时,那么守护线程就会随主线程一起结束,但实际情况不是这样。

只有一个子进程(守护线程)的情况:

import threading
def test():
	x = 0
	for i in range(5):
		x = i + x
		print(x)
	print(str(threading.enumerate()))  # 打印出当前进程中的所有线程
if __name__ == '__main__':
	thread = threading.Thread(target=test)
	thread.setDaemon(True)
	thread.start()
	print('nihao')

这里只在上面代码中加了setDaemon(True),结果只出现了 0nihao,执行不同次可能结果不同哈,因为线程有时候快一点,有时候慢一点。这确实印证了,主进程结束了,守护进程就结束了,但是在多增加一个非守护进程之后结果就不是这样了,如下:

import threading
def test1():
	while True:
		print('nihao')
def test2():
	while True:
		print(str(threading.enumerate()))
if __name__ == '__main__':
	thread1 = threading.Thread(target=test1)
	thread2 = threading.Thread(target=test2)
	thread1.setDaemon(True)
	thread1.start()
	thread2.start()

这个脚本会无限次地运行,此处我截取一部分结果如下:

在这里插入图片描述
可以看出主线程已经停止了,但是守护线程test1还是在工作,还是在打印 nihao这个字符,也就表明主线程停止不会导致守护线程结束,而是不再理会守护线程的完成状态,即在有守护线程的情况下,只要其它的非守护线程和主线程都结束了,整个任务就结束了,不用考虑守护线程是否完成。

使用join的情况:

因此为了避免主线程提前结束导致子线程未完成的情况,join横空出世,使用join方法表示主线程的任务在碰到子线程join方法时会阻塞,此时主线程任务不再继续,而是等待所有子线程任务全部结束后,主线程才会继续运行直到停止。

上面的第二个例子,加入join()后:

import threading
def test():
	x = 0
	for i in range(5):
		x = i + x
		print(x)
	print(str(threading.enumerate()))  # 打印出当前进程中的所有线程
if __name__ == '__main__':
	thread = threading.Thread(target=test)
	thread.setDaemon(True)
	thread.start()
	thread.join()
	print('nihao')

结果如下:

在这里插入图片描述
可以看到这样结果就很好看了,也是很有条理的。总之,这就是join()的作用啦。

join()方法还有一个参数为timeout,即时间限制,对于守护线程的效果是经过timeout的时间后此守护线程就结束。而对于非守护线程,那么timeout时间后子线程还是可以继续执行,但此时主线程会开始执行,主线程任务执行后会进入停止即stop状态。

例:

import threading
def test():
	while True:
		print('x')
		print(str(threading.enumerate()))
if __name__ == '__main__':
	thread = threading.Thread(target=test)
	thread.start()
	thread.join(0.1)
	print(str(threading.enumerate()))

结果如下(一部分):

在这里插入图片描述

叮!

参考:Python多线程与多线程中join()的用法
参考:Python:线程为什么搞个setDaemon

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值