线程等待属性操作和方法操作


前言

进程靠线程执行代码,至少有一个主线程,其他线程是工作线程
主线程是第一个启动的线程
父线程:如果线程中启动了一个线程B,A就是B的父线程
子线程:B就是A的子线程

1. daemon属性

如果有non-daemon线程的时候,主线程退出时,也不会杀掉所有daemon线程,直到所有non-daemon线程全部结束,如果还有daemon线程,主线程需要退出,会结束所有daemon线程,退出

1.1 线程为 non-daemon

主线程扫描所有线程,只要存在non-daemon线程,主线程就等待non-daemon线程执行完毕后才退出

案例如下

  • 线程为non-daemon线程
import time
import threading

def foo():
    time.sleep(5)
    for i in range(5):
        print(i)

#主线程是non-daemon线程,主进程
t = threading.Thread(target=foo,daemon=False)
t.start()
print('Main Thread Exiting')


#运行结果:
Main Thread Exiting
0
1
2
3
4

1.2 线程为 daemon

当主线程运行结束时,主线程不等待其他线程是否已经完成,直接退出程序

import time
import threading

def foo():
    time.sleep(5)
    for i in range(5):
        print(i)

#主线程是non-daemon线程
t = threading.Thread(target=foo,daemon=True)
t.start()

#运行结果
Main Thread Exiting

1.3 两种线程共存

案列如下:
non-daemon线程执行时长大于daemon线程时,表现为daemon线程也会执行完成

import time
import threading

def foo(n):
    for i in range(n):
        print(i)
        time.sleep(1)

t1 = threading.Thread(target=foo,args=(2,),daemon=True)
t1.start()

t2 = threading.Thread(target=foo,args=(4,),daemon=False)
t2.start()

time.sleep(1)
print('Main Thread Exiting')

#运行结果
0
0
Main Thread Exiting
1
1
2
3

daemon线程执行时长大于non-daemon线程时,表现为并非所有non-daemon线程会执行完成

import time
import threading

def foo(n):
    for i in range(n):
        print(i)
        time.sleep(1)

t1 = threading.Thread(target=foo,args=(4,),daemon=True)
t1.start()

t2 = threading.Thread(target=foo,args=(2,),daemon=False)
t2.start()

time.sleep(1)
print('Main Thread Exiting')
#运行结果
0
0
Main Thread Exiting
1
1

说明主线程是否退出线程,取决于:进程内是否存储non-daemon线程,若不存在non-daemon时直接退出程序

2. join方法

join主要是阻塞功能,线程一旦join到某个父线程或者主线程时,父线程或主线程就阻塞到join位置,直到发起join的线程运行完成后才释放阻塞,通常在daemon线程中使用

import time
import threading

def foo(n):
    for i in range(n):
        print(i)
        time.sleep(1)

t1 = threading.Thread(target=foo,args=(4,),daemon=True)
t1.start()
t1.join()
print('Main Thread Exiting')

#运行结果:
0
1
2
3
Main Thread Exiting

总结
join(timeout=None),是线程的标准方法之一

  • 一个线程中调用另一个线程的join方法,调用者将被阻塞,直到被调用者线程终止。
  • 一个线程可以被join多次
  • timeout参数指定调用者等待多久,没有设置超时,就一直等待被调用线程结束
  • 调用谁的join方法,就是join谁,就要等谁

3. 循环等待

3.1 event事件

event根据源码可知,event本身是一个类,在类属性中有一个flag属性,在flag的属性值初始为false,但是可以通过set方法重置为true,另外注意wait方法,wait在等待时间区间内,若flag从fasle重置为true,则wait函数返回值Ture,若没有发生变化,而且一旦set()后不再等待,则wait函数返回值为FALSE,此项非常重要,可以利用此技巧进行循环等待。

3.2 event知识

在event类的学习过程中,要抛弃运维时学习到的模型,因为那些模型概念,仅仅是模型不能帮助你学习东西,返回会带来误解性的东西

名称含义
set()标记设置为True
clear()标记设置为False
is_set()标记是否为True
wait(timeout=None)设置等待标记为True的时长,None为无限等待,等到返回True,未等到超时了返回False

3.3 循环等待技巧

import threading from Event,Thread
def do(event:Event,interval:int):
    while not event.wait(interval)
    #循环等待,若event在等待interval周期内没有set(),返回false,因此再次进入循环
        print('ok')
e = Event()
Thread(target=do,args=(e,3)).start()
e.wait(10)
e.set()
print("main exit")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值