'''使用类继承的方式,实现信号量、事件功能操作。
具体案例:第一个线程中获取当前时间,判断当前时间3秒之后,触发“事件”对象。
在另一个线程中,作为数学考试结束的判断变量,否则一直处于考试中,并打印。'''
import threading#导入库threading,time
import time
event = threading.Event()#先创建一个event 方便下面使用
event.set()#设置event默认为True
class Get_time(object): #创建类Get_time来获取时间 判断时间
def __init__(self,start_time):#获取一个初始时间
self.start_time=start_time
def give_time(self,time0):#创建方法 来判断 当时间为3秒时 event设置为False
while True:
if time.time()-time0<3:
print(time.time()-time0)
time.sleep(0.5)
event.set()
else:
event.clear()
break
class Kaoshi(object):#创建类Kaoshi来进行考试 当event设置为False时考试结束 否则一直打印正在考试
def print_kaoshi(self,n,semaphore):
while True:
time.sleep(0.1)
if event.is_set():
semaphore.acquire()#获取semaphore来实现多个位置同时运行
print("考生{0}正在考试".format(n))
semaphore.release()
else:
print("考试结束")
break
class Start_kaoshi(Get_time,Kaoshi):#创建类Start_kaosh来总执行 继承Get_time,Kaoshi
def __init__(self,start_time):
Get_time.__init__(self,start_time)#调用 Get_time的init
Kaoshi.__init__(self)#调用 Kaoshi的init
def Start(self):#设置方法 来实现总开关
semaphore=threading.Semaphore(3)#创建3个semaphore
thread2 = threading.Thread(target=self.give_time, args=(self.start_time,))#先创建控制时间的线程
thread2.start()
time.sleep(0.1)
for i in range(3):#创建3个考试的线程
t=threading.Thread(target=self.print_kaoshi,args=(i,semaphore))
t.start()
time_start=time.time()#获取初始时间
c1=Start_kaoshi(time_start)#实例化c1
c1.Start()#考试开始
信号量
信号量可以让程序允许固定的线程数
threading.Semaphore(thread_number)
semaphore=threading.Semaphore(3)#设置信号量有3个(最多同时运行3个线程)
semaphore.acquire()#获得一个信号量
semaphore.release()#释放信号量
import threading
import time
def run(n):
sm.acquire()
print(n)
time.sleep(1)
sm.release()
if __name__ == '__main__':
sm=threading.Semaphore(5)
for i in range(10):
t=threading.Thread(target=run,args=(i,))
t.start()
条件变量:
条件变量是在lock的基础上进行的完善,相比lock有更多的功能,可以锁的同时,可以设置等待的时间(wait),并可以通知(notify)来取消等待。
threading.Condition()
acquire(timeout)
调用Condition类关联的Lock/RLock的acquire()方法。
release()
调用Condition类关联的Lock/RLock的release()方法。
wait(timeout)
1)线程挂起,直到收到一个notify通知或者等待时间超出timeout才会被唤醒;
2)注意:wait()必须在已获得Lock的前提下调用,否则会引起RuntimeError错误。
notify(n=1)
1)唤醒在Condition的waiting池中的n(参数n可设置,默认为1)个正在等待的线程并通知它,受到通知的线程将自动调用acquire()方法尝试加锁;
2)如果waiting池中有多个线程,随机选择n个唤醒;
3)必须在已获得Lock的前提下调用,否则将引发错误。
notify_all()
唤醒waiting池中的等待的所有线程并通知它们
import threading
def run(x):
con.acquire()
print("线程{0}".format(x))
print("线程{0}挂起".format(x))
con.notify(1)#通过注释这一行可以看到区别
con.wait(5)
print("线程{0}再次气动".format(x))
con.release()
if __name__=="__main__":
con=threading.Condition()
for i in range(50):
a=threading.Thread(target=run,args=(i,))
a.start()
事件
事件可以控制所有的线程,让所有的线程同时去等待/运行
threading.Event()
event=threading.Event()#这一行一定要放前面 血的教训 这样作为全局变量才能直接被用
event.wait(timeout=None):
调用该方法的线程会被阻塞,如果设置了timeout参数,超时后,线程会停止阻塞继续执行;event.set():
将event的标志设置为True,调用wait方法的所有线程将被唤醒;
event.clear():
将event的标志设置为False,调用wait方法的所有线程将被阻塞;
event.is_set():判断event的标志是否为True。
例子:
import time, threading
event = threading.Event()
# 交通灯
def lighter():
count = 0
while True:
if count < 5: # 绿灯
event.set() #设置标志位
print("\033[42;1m 绿灯亮\033[0m")
elif count > 10:
count =0 # 清零重新计数
else: # 红灯
event.clear() # 清空标志位
print("\033[41;1m 红灯亮\033[0m")
time.sleep(1)
count += 1
# 车辆
def car(name):
while True:
if event.is_set(): # 绿灯亮
print("[%s]绿灯行..." % name)
time.sleep(1)
else:
print("[%s]红灯停!!!" % name)
event.wait() # 等待标志位设定
print("\033[34;1m绿灯出发\033[0m")
# 启动交通灯
t_lighter = threading.Thread(target=lighter)
t_lighter.start()
# 放入车辆
t_car1 = threading.Thread(target=car, args=("奥迪车",))
t_car2 = threading.Thread(target=car, args=("大众车",))
t_car1.start()
t_car2.start()