如何改变 Python 中线程的执行顺序
一、主线程会等待所有的子线程结束后才结束
首先我看下最普通情况下,主线程和子线程的情况。
import threading
from time import sleep, ctimedef sing():for i in range(3):print("正在唱歌...%d" % i)sleep(1)def dance():for i in range(3):print("正在跳舞...%d" % i)sleep(1)if __name__ == '__main__':print('---开始---:%s' % ctime())t1 = threading.Thread(target=sing)t2 = threading.Thread(target=dance)t1.start()t2.start()print('---结束---:%s' % ctime())
运行结果:
最后一行打印的代码就算在一开始运行了,程序也不会结束。
只有等待所有的子线程(sing 和 dance)都执行完毕,主线程才会结束,即程序结束。
二、默认状态下,多线程的执行顺序是不确定的
我们先来看一段代码:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import threading
import timeclass MyThread(threading.Thread):def run(self):for i in range(3):time.sleep(1)msg = "I'm "+self.name+' @ '+str(i)print(msg)def test():for i in range(5):t = MyThread()t.start()if __name__ == '__main__':test()
运行结果:
I'm Thread-1 @ 0
I'm Thread-2 @ 0
I'm Thread-3 @ 0
I'm Thread-4 @ 0
I'm Thread-5 @ 0
I'm Thread-1 @ 1
I'm Thread-3 @ 1
I'm Thread-2 @ 1
I'm Thread-4 @ 1
I'm Thread-5 @ 1
I'm Thread-1 @ 2
I'm Thread-3 @ 2
I'm Thread-2 @ 2
I'm Thread-4 @ 2
I'm Thread-5 @ 2
每次的运行结果可能都不一样,但大体差不多。
说明:
从代码和执行结果我们可以看出,多线程程序的执行顺序是不确定的。
当执行到 sleep 语句时,线程将被阻塞,到 sleep 结束后,线程进入就绪状态,等待调度,而线程调度将自行选择一个线程执行。
上面的代码中只能保证每个线程都运行完整个 run 函数,但是线程的启动顺序、run 函数中每次循环的执行顺序都不能确定。
总结
每个线程默认有一个名字,尽管上面的例子中没有指定线程对象的 name,但是 python 会自动为线程指定一个名字。
当线程的 run() 方法结束时该线程完成。
无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。
三、Python daemon 守护线程详解
当程序中拥有多个线程时,主线程执行结束并不会影响子线程继续执行。
换句话说,只有程序中所有线程全部执行完毕后,程序才算真正结束。
Python 还支持创建另一种线程,称为守护线程(或后台线程)。
此类线程的特点是,当程序中主线程及所有非守护线程执行结束时,未执行完毕的守护线程也会随之消亡,程序将结束运行。
守护线程本质也是线程,因此其创建方式和普通线程一样,唯一不同之处在于,将普通线程设为守护线程,需通过线程对象调用其 damon 属性,将该属性的值改为 True。
注意:线程对象调用 daemon 属性必须在调用 start() 方法之前,否则 Python 解释器将报 RuntimeError 错误。
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import threadingdef action(len):for i in range(len):print(threading.current_thread().getName() + "," + str(i))def main():t1 = threading.Thread(target=action, args=(10,))# 设置子线程为守护进程t1.daemon = Truet1.start()for i in range(3):print(threading.current_thread().getName()+','+str(i))if __name__ == "__main__":main()
运行结果:
Thread-1,0
MainThread,0
MainThread,1
MainThread,2
程序中,子线程里的程序就循环了一次,接着主线程执行完后,子线程就不打印信息了。
由于该程序中除了守护线程就只有主线程,因此只要主线程执行结束,则守护线程也随之消亡。
四、控制线程执行顺序
通过前面的学习我们知道,主线程和子线程会轮流获得 CPU 的资源。
但有时候,我们想让某个子线程先执行,然后再让主线程执行代码,该如何实现呢?
很简单,通过调用线程对象的 join() 方法即可。
join() 方法的功能是在程序指定位置,优先让该方法的调用者使用 CPU 资源。
该方法的语法格式如下:
thread.join( [timeout] )
timeout 参数作为可选参数,其功能是指定 thread 线程最多可以霸占 CPU 资源的时间(以秒为单位)。
如果省略,则默认直到 thread 执行结束(进入死亡状态)才释放 CPU 资源。
我们仍旧拿上面的例子来举例:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import threadingdef action(len):for i in range(len):print(threading.current_thread().getName() + "," + str(i))def main():t1 = threading.Thread(target=action, args=(10,))# 设置子线程为守护进程t1.daemon = Truet1.start()t1.join()for i in range(3):print(threading.current_thread().getName()+','+str(i))if __name__ == "__main__":main()
我们在子线程调用的后面,添加了 t1.join()。
运行结果:
Thread-1,0
Thread-1,1
Thread-1,2
Thread-1,3
Thread-1,4
Thread-1,5
Thread-1,6
Thread-1,7
Thread-1,8
Thread-1,9
MainThread,0
MainThread,1
MainThread,2
上面的例子中,t1 线程调用了 join() 方法,并且没有指定具体的 timeout 参数值。
这意味着如果程序想继续往下执行,必须先执行完 t1 子线程。
如何改变 Python 中线程的执行顺序相关推荐
- python类中方法的执行顺序-Python实例化class的执行顺序实例方法
Python中实例化class的执行顺序示例详解 前言 本文主要介绍了关于Python实例化class的执行顺序的相关内容,下面话不多说了,来一起看看详细的介绍吧 Python里对类的实例化时有怎样的 ...
- python类中方法的执行顺序-Python中实例化class的执行顺序示例详解
前言 本文主要介绍了关于Python实例化class的执行顺序的相关内容,下面话不多说了,来一起看看详细的介绍吧 Python里对类的实例化时有怎样的顺序 一般来说一个类里面有类变量和方法,比如我们定 ...
- python中线程里面多线程_Python中的线程和多线程是什么
一.线程的概念 一个进程里面至少有一个控制线程,进程的概念只是一种抽象的概念,真正在CPU上面调度的是进程里面的线程,就好比真正在地铁这个进程里面工作的实际上是地铁里面的线程,北京地铁里面至少要有一个 ...
- python中线程和进程_python中线程和进程的简单了解
一.操作系统.应用程序 1.硬件:硬盘.cpu.主板.显卡........ 2.装系统(本身也是一个软件): 系统就是一个由程序员写出来的软件,该软件用于控制计算机得硬盘,让他们之间进行互相配合. 3 ...
- mysql关键字使用顺序_MySQL数据库之单表查询中关键字的执行顺序
MySQL数据库之单表查询中关键字的执行顺序 1 语法顺序 select distinct from where group by having order by limit 2 执行顺序 from ...
- 关于线程的执行顺序,可能真的只是你以为的你以为
摘要:今天,我们就一起来看看线程到底是如何执行的,它的顺序又是怎样的? 本文分享自华为云社区<线程的执行顺序与你想的不一样!!>,作者:冰 河 . 一.线程的执行顺序是不确定的 调用Thr ...
- Python中线程间通信
Python中线程间通信 一.前言 二.什么是互斥锁 三.使用互斥锁 四.使用队列在线程间通信 五.关于线程需要注意的两点 一.前言 我们已经知道进程之间不能直接共享信息,那么线程之间可以共享信息 ...
- mysql数据库查询关键字级别_MySQL数据库之单表查询中关键字的执行顺序
MySQL数据库之单表查询中关键字的执行顺序 1 语法顺序 select distinct from where group by having order by limit 2 执行顺序 from ...
- 整理:sql server 中sql语句执行顺序
原文地址为: 整理:sql server 中sql语句执行顺序 SQL Server 查询处理中的各个阶段(SQL执行顺序) SQL 不同于与其他编程语言的最明显特征是处理代码的顺序.在大数编程语言中 ...
最新文章
- 谈谈WEB开发中的苦大难字符集问题
- 浏览器同部署了https的服务器交互的过程
- python官网下载步骤linux-linux下安装python
- 遭遇IE8下的JavaScript兼容问题
- C++ Primer 5th笔记(chap 15 OOP)概述
- server 2008 配置php mysql_Win2008 Server配置PHP环境
- asp.net 拦截html,关于c#:如何在-ASPNET-Core-中实现全局异常拦截
- php websocket 是否在线_看完让你彻底理解WebSocket原理,附实战代码(包含前端和后端)...
- LeetCode 940. 不同的子序列 II(动态规划)
- H5 Canvas下雨特效
- Bezier(贝塞尔)曲线(五阶)的轨迹规划在自动驾驶中的应用(六)
- 用Entlib的配置程序块遇到的问题
- Kneron用“重组”方案精简深度学习算法,芯片产品明年开售
- 解决启用GTID binlog新安装完的MySQL提示无法登录
- 机械表加智能表,双表成为富人标配
- h5居中loading_H5样式与布局 --常用居中方法
- Java流处理之序列化和打印流
- word:多级标题快捷生成
- 指针数组和二维数组指针
- 数据表对应关系(一对一、一对多、多对多)