改变 Python 中线程执行顺序的方法

 更新时间:2020年09月24日 08:52:47   作者:小名叫小明  
这篇文章主要介绍了改变 Python 中线程的执行顺序的方法,帮助大家更好的理解和学习python,感兴趣的朋友可以了解下

一、主线程会等待所有的子线程结束后才结束

首先我看下最普通情况下,主线程和子线程的情况。

import threading
from time import sleep, ctime

def 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)都执行完毕,主线程才会结束,即程序结束。

二、默认状态下,多线程的执行顺序是不确定的

我们先来看一段代码:

import threading
import time

class 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 错误。

import threading

def 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 = True
 t1.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 资源。

我们仍旧拿上面的例子来举例:

import threading

def 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 = True
 t1.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 中线程的执行顺序的资料请关注脚本之家其它相关文章!

相关文章

  • 解决virtualenv -p python3 venv报错的问题

    解决virtualenv -p python3 venv报错的问题

    这篇文章主要介绍了解决virtualenv -p python3 venv报错的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Python3.7 版本 lxml 模块无法导入etree 问题及解决方法

    Python3.7 版本 lxml 模块无法导入etree 问题及解决方法

    这篇文章主要介绍了Python3.7 版本 lxml 模块无法导入etree 问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • 六个Python3中使用最广泛的内置函数总结

    六个Python3中使用最广泛的内置函数总结

    这篇文章主要为大家详细介绍了六个Python3中使用最广泛的内置函数:Lamdba 函数、Map 函数、Filter 函数、Reduce 函数、Enumerate 函数和Zip 函数,需要的可以参考一下
    2022-08-08
  • 使用python提升图片清晰度的常见方法

    使用python提升图片清晰度的常见方法

    在Python中,提升图片清晰度可以通过多种方法实现,其中一些常见的方法包括使用图像处理库如OpenCV和Pillow,下面小编就来和大家介绍一下具体实现方法吧
    2025-04-04
  • Python新手教程之while循环20例

    Python新手教程之while循环20例

    循环的作用就是让指定的代码重复的执行,while循环最常用的应用场景就是让执行的代码按照指定的次数重复执行,这篇文章主要给大家介绍了关于Python新手教程之while循环20例的相关资料,需要的朋友可以参考下
    2024-05-05
  • Python中的breakpoint方法使用小结

    Python中的breakpoint方法使用小结

    breakpoint 是 Python 3.7 及以后版本中一个非常有用的内置函数,本文主要介绍了Python中的breakpoint方法,具有一定的参考价值,感兴趣的可以了解一下
    2025-04-04
  • Python如何向IP地址发送字符串

    Python如何向IP地址发送字符串

    在Python中,向IP地址发送字符串通常意味着你需要通过某种协议来实现通信,最常见的协议包括TCP和UDP,这篇文章主要介绍了Python向IP地址发送字符串的示例代码,需要的朋友可以参考下
    2024-08-08
  • TensorFlow实现自定义Op方式

    TensorFlow实现自定义Op方式

    今天小编就为大家分享一篇TensorFlow实现自定义Op方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02
  • Python中函数的参数类型详解

    Python中函数的参数类型详解

    这篇文章主要介绍了Python中函数的参数类型详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07
  • python3 selenium 切换窗口的几种方法小结

    python3 selenium 切换窗口的几种方法小结

    今天小编就为大家分享一篇python3 selenium 切换窗口的几种方法小结,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05

最新评论