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


往期内容:

1、什么是多线程?

2、添加线程

0x00 不使用join()的结果

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

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()

预计输出结果:

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

实际输出结果:

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

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

0x01 使用join()的结果

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

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

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

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

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

0x02 添加第2个线程

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

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

输出的一种结果:

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

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

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

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

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

其输出结果如下:

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

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

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

其输出结果如下:

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

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

0x04 最终代码及输出结果

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

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

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

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()

输出结果:

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

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


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