当前位置:   article > 正文

python多线程threading_python threading.thread参数

python threading.thread参数

Python 3.X实现多线程的是threading模块,使用它可以创建多线程程序,并且在多线程间进行同步和通信。因为是一个模块,所以使用前必须先导入:

import threading

Python支持两种创建多线程的方式:
•  通过threading.Thread()创建。
•  通过继承threading.Thread类创建。

通过threading.Thread()创建

Thread()的语法如下:

threading.Thread(group=None, target=None, name=None, args=(), kwargs={},daemon=None) 

group:必须为None,与ThreadGroup类相关,一般不使用。

target:线程调用的对象,就是目标函数。

name:为线程起个名字。默认是Thread-x,x是序号,由1开始,第一个创建的线程名字就是Thread-1。

args:为目标函数传递实参,元组。

kwargs:为目标函数传递关键字参数,字典。

daemon:用来设置线程是否随主线程退出而退出。

参数虽然很多,但是实际常用的是target和args,可以用例子1来做演示。

例1

  1. import threading#导入模块
  2. def test(x,y):#定义测试函数
  3. for i in range(x,y):
  4. print(i)
  5. thread1=threading.Thread(name='t1',target=test,args=(1,10))
  6. thread2=threading.Thread(name='t2',target=test,args=(11,20))
  7. thread1.start() #启动线程1
  8. thread2.start() #启动线程2

第8~9行的start()函数用来启动线程。如果按照先执行一段代码再执行一段代码的传统形式,那么上述代码应该是先输出1~10再输出11~20,但是运行程序后效果却如下图所示

再运行一次,发现结果变了

这是因为两个线程会并发运行,所以结果不一定每次都是顺序的1~10,这是根据CPU给两个线程分配的时间片段来决定的。多运行几次代码,就会发现每次效果都有所不同。

通过继承threading.Thread类创建

  1. import threading#导入模块
  2. class mythread(threading.Thread):#继承threading.Thread类
  3. def run(myself):#定义测试函数
  4. for i in range(1,10):
  5. print(i)
  6. thread1=mythread()
  7. thread2=mythread()
  8. thread1.start() #启动线程1
  9. thread2.start() #启动线程2

第3行自定义一个类继承自threading.Thread,然后重写父类的run()方法,会在线程启动时(执行start())自动执行。如果把第10~11行的start()换为run(),就会发现run()仅仅是被当作一个普通的函数使用。只有在线程start时,它才是多线程的一种调用函数。也就是不存在并行,只会串行地执行。

主线程

在Python中,主线程是第一个启动的线程。我们需要了解两个概念:

父线程:如果线程A中启动了一个线程B,那么A就是B的父线程。

子线程:如果线程A中启动了一个线程B,那么B就是A的子线程。

创建线程时有一个daemon属性,可以用来判断主线程。当daemon设置为False时,子线程不会随主线程退出而退出,主线程会一直等着子线程执行完。当daemon设置为True时,当主线程结束,其他子线程就会被强制结束。

使用daemon属性时有以下几个注意事项:

daemon属性必须在start()之前设置,否则会引发RuntimeError异常。

每个线程都有daemon属性,可以显式设置,也可以不设置(取默认值None)。

如果子线程不设置daemon属性,就取当前线程的daemon来设置。子线程继承子线程的daemon值,作用和设置None一样。

从主线程创建的所有线程不设置daemon属性,默认都是daemon=False。

为了演示主线程的例子,我们需要学习一个time模块中的sleep()函数(用于推迟线程的执行,默认时间是秒)。下面引入time模块来演示例子

  1. import threading#导入模块
  2. import time
  3. def test():
  4. time.sleep(3)
  5. for i in range(10):
  6. print(i)
  7. thread1=threading.Thread(target=test,daemon=False)
  8. thread1.start()
  9. print('主线程完成了')

上述代码的执行结果如图

当主线程完毕时,子线程依然会执行,就是输出0~9。如果将第9行的daemon=False改为daemon=True,那么程序应该只输出“主线程完成了”,因为主线程完成后会强制子线程退出,但实际效果却与上图一致,这又是为什么呢?

原来这样的测试并不适用于IDLE环境中的交互模式或脚本运行模式,因为在该环境中的主线程只有在退出Python IDLE时才终止。

阻塞线程

多线程提供了一个方法join(),简单来说是一个阻塞线程。在一个线程中调用另一个线程的join()方法,调用者将被阻塞,直到被调用线程终止。其语法是:

join(timeout=None)

timeout参数指定调用者等待多久,没有设置时就一直等待被调用线程结束。其中,一个线程可以被join多次。

  1. import threading#导入模块
  2. import time
  3. def test():
  4. time.sleep(3)
  5. for i in range(10):
  6. print(i)
  7. thread1=threading.Thread(target=test,daemon=False)
  8. thread1.start()
  9. print('主线程完成了')

前面学习daemon属性时已经提到,当取默认值或者设置为False时,主线程退出后子线程依然会执行。因为子线程当时设置了sleep(),所以先执行了主线程的print输出,然后才输出0~9。此时,如果在start()行后面添加如下join()方法:

thread1.join()

这样在输出时,主线程会等到输出0~9后再执行自己的print输出,效果如图

判断线程是否是活动的

除了前面介绍的join(),其实threading.Thread类还提供了很多方法,主要方法参见表 

run()、start()、join()在前面都介绍过,其他3个方法可以用例子来说明。 

isAlive()、getName()、setName()的例子

  1. import threading#导入模块
  2. import time
  3. def test():
  4. time.sleep(6)
  5. for i in range(10):
  6. print(i)
  7. thread1=threading.Thread(target=test)
  8. print('1.当前线程是否是活动的:',thread1.isAlive())
  9. thread1.start()
  10. print('2.当前线程是否是活动的:',thread1.isAlive())
  11. print('当前线程',thread1.getName())
  12. thread1.join()
  13. print('线程完毕')

在第10行时,因为还没有使用start()启动线程,所以当前线程不是活动的状态。执行到第12行时就输出了True。第13行获取线程的名称,因为创建线程时没有使用name属性,所以线程的默认名字是Thread-x这种形式。

在代码运行期间,也可以使用setName()更改线程的名字。下面修改代码为例子

  1. import threading#导入模块
  2. import time
  3. def test():
  4. time.sleep(6)
  5. for i in range(10):
  6. print(i)
  7. thread1=threading.Thread(target=test)
  8. print('1.当前线程是否是活动的:',thread1.isAlive())
  9. thread1.start()
  10. print('2.当前线程是否是活动的:',thread1.isAlive())
  11. thread1.setName('Th-1')
  12. print('当前线程',thread1.getName())
  13. thread1.join()
  14. print('线程完毕')

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/143419
推荐阅读
相关标签
  

闽ICP备14008679号