Python Threading 学习笔记 | 3、join功能

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-note

本文分享自微信公众号 - TeamsSix(OldCat0111)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DevOps持续集成

如何设计一条前端项目发布流水线?

项目配置部分主要是将网站源代码上传到github,然后搭建用户访问的web服务器。再经过Jenkins+saltstack配置发布代码到web服务器。

9120
来自专栏DevOps持续集成

Jenkins实践文档-Jenkins集成Gitlab

12920
来自专栏Java架构师学习

那些能帮助你提升十倍开发效率的优质工具

Java世界中存在着很多工具,从著名的IDE(例如Eclipse,NetBeans和IntelliJ IDEA)到JVM profiling和监视工具(例如JC...

12950
来自专栏DevOps持续集成

Jenkins集成Gitlab

6820
来自专栏搜云库技术团队

Redis集群下的RedLock算法(真分布式锁) 实践

在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段。 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很...

8620
来自专栏我的前端路

通俗易懂的 Git 教程:核心概念

Git 是目前世界上最优秀的分布式版本控制系统。版本控制系统是能够随着时间的推进记录一系列文件的变化以便于你以后想要的退回到某个版本的系统。版本控制系统分为三大...

9400
来自专栏方丈的寺院

guava缓存批量获取的一个坑

Guava Cache是Google开源的Java工具集库Guava里的一款缓存工具,一直觉得使用起来比较简单,没想到这次居然还踩了一个坑。

11340
来自专栏DevOps持续集成

Gitlab+Drbd高可用方案(主备模式)

直接在清华大学镜像站下载:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/

43030
来自专栏编程之旅

修改Host文件优化github访问速度

最近可能是一些不为人知的原因,我在家里使用电脑时,github 访问的速度实在难以忍受,就连常规的提交代码都非常的慢,尝试了一下 ping github.com...

29950
来自专栏DevOps持续集成

Jenkins Pipeline高级用法-ShareLibrary

https://github.com/zeyangli/ShareLibrary-jenkins.git

13670

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励