【Python Threading 学习笔记】3、join功能


往期内容:

1、什么是多线程?

2、添加线程

0x00 不使用join()的结果

首先在上一节的示例基础上进行简单修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import time
import threading

def thread_jobs(): # 定义要添加的线程
print('任务1开始\n')
for i in range(10):
time.sleep(0.1)
print('任务1结束\n')

def main():
thread = threading.Thread(target=thread_jobs,name='任务1') # 定义线程
thread.start() # 开始线程
print('所有任务已完成\n')

if __name__ == '__main__':
main()

预计输出结果:

1
2
3
4
# python 3_join.py
任务1开始
任务1结束
所有任务已完成

实际输出结果:

1
2
3
4
# python 3_join.py
任务1开始
所有任务已完成
任务1结束

可以看到在线程还没有结束的时候,程序就开始运行之后的代码了,也就是说线程和其他部分的程序都是同步进行的,如果想要避免这种情况,想要程序按照代码顺序执行的话,就需要用到join功能。

0x01 使用join()的结果

在源代码thread.start()下加入thread.join()即可,原来代码的main函数就变成这样:

1
2
3
4
5
def main():
thread = threading.Thread(target=thread_jobs,name='任务1') # 定义线程
thread.start() # 开始线程
thread.join() #加入join功能
print('所有任务已完成\n')

这里就表示必须要等到任务1这个线程结束后,才能执行thread.join()之后的代码,代码运行结果如下:

1
2
3
4
# python 3_join.py
任务1开始
任务1结束
所有任务已完成

使用join控制多个线程的执行顺序很关键。

0x02 添加第2个线程

这时如果我们加入第2个线程,但是不加入join功能,看看又是什么样,第2个线程的任务量较小,因此比第1个线程会更快执行,加入的第2个线程如下:

1
2
3
def thread_jobs2(): # 定义第2个线程
print('任务2开始\n')
print('任务2结束\n')

输出的一种结果:

1
2
3
4
5
6
# python 3_join.py
任务1开始
任务2开始
任务2结束
所有任务已完成
任务1结束

注意这个时候任务1和任务2都没有添加join,也就是说输出的内容是什么完全看谁执行的快,谁先执行完谁就先输出,因此这里的输出结果并不唯一,这种杂乱的输出方式是不能接收的,所以需要使用join来控制。

0x03 在不同位置使用join()的结果

如果在任务2开始前只对任务1加入join功能:

1
2
3
4
thread.start()  # 开始线程1
thread.join() # 对任务1加入join功能
thread2.start() # 开始线程2
print('所有任务已完成\n')

其输出结果如下:

1
2
3
4
5
6
# python 3_join.py
任务1开始
任务1结束
任务2开始
任务2结束
所有任务已完成

可以看到程序会先执行任务1再执行接下来的操作,如果在任务2开始后只对任务1加入join功能:

1
2
3
4
thread.start()  # 开始线程1
thread2.start() # 开始线程2
thread.join() # 对任务1加入join功能
print('所有任务已完成\n')

其输出结果如下:

1
2
3
4
5
6
# python 3_join.py
任务1开始
任务2开始
任务2结束
任务1结束
所有任务已完成

任务1先于任务2启动,但由于任务2的处理时间较短,因此先于任务1完成,而由于任务1加入了join,因此“所有任务已完成”也在任务1完成后再显示。

0x04 最终代码及输出结果

如果只对任务2加入join,同样输出结果就是要先等任务2执行完再执行其他程序,但是为了避免不必要的麻烦,推荐下面这种1221的V型排布,毕竟如果每个线程start()后就加入其join(),那就和单线程无异了。

1
2
3
4
thread.start()  # 开始线程1
thread2.start() # 开始线程2
thread2.join() # 对任务2加入join功能
thread.join() # 对任务1加入join功能

最终完整代码及输出结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import time
import threading

def thread_jobs(): # 定义第1个线程
print('任务1开始\n')
for i in range(10):
time.sleep(0.1)
print('任务1结束\n')

def thread_jobs2(): # 定义第2个线程
print('任务2开始\n')
print('任务2结束\n')

def main():
thread = threading.Thread(target=thread_jobs,name='任务1') # 定义线程1
thread2 = threading.Thread(target=thread_jobs2, name='任务2') # 定义线程2
thread.start() # 开始线程1
thread2.start() # 开始线程2
thread2.join() # 对任务2加入join功能
thread.join() # 对任务1加入join功能
print('所有任务已完成\n')

if __name__ == '__main__':
main()

输出结果:

1
2
3
4
5
6
# python 3_join.py
任务1开始
任务2开始
任务2结束
任务1结束
所有任务已完成

参考文章:https://morvanzhou.github.io/tutorials/python-basic/threading
代码项目地址:https://github.com/teamssix/Python-Threading-study-notes


文章作者: Teams Six
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Teams Six !
评论
 上一篇
【Python Threading 学习笔记】4、Queue功能 【Python Threading 学习笔记】4、Queue功能
往期内容: 1、什么是多线程? 2、添加线程 3、join功能 0x00 关于Queuequeue模块实现了各种【多生产者-多消费者】队列,可用于在执行的多个线程之间安全的交换信息。 queue的常用方法: 123456789101112
2019-11-03
下一篇 
【Python Threading 学习笔记】2、添加线程 【Python Threading 学习笔记】2、添加线程
往期内容:1、什么是多线程? 这一节主要学习Threading模块的一些基本操作,如获取线程数,添加线程等。 首先导入Threading模块 1import threading 获取已激活的线程数 1threading.active_co
2019-11-01
  目录