Event
一个线程需要根据另外一个线程的状态来确定自己的下一步操作,需要调用threading库中Event对象;Event包含一个可由线程设置的信号标志,在初始情况下,event对象的标志位为假(false);。如果一个线程等待一个event对象,而这个event对象标志为假,那么这个线程将会被一直阻塞到标志为真(true);。
同理:一个线程如果将一个event对象的信号标志设置为真,它将唤醒所有等待这个event对象的线程。
如果一个线程等待一个已经被设置为真的event对象,那么它将忽略这个事件,继续执行。
#!/usr/bin/env python# encoding: utf-8"""@author: 侠之大者kamil@file: Event_test.py@time: 2016/3/23 9:42"""from threading import Thread ,Eventimport timedef countdown(n,started_evt): print('countdown starting',time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())) started_evt.set() while n >0: print("T-time_kamil:",n) n -=1 time.sleep(2)started_evt = Event()print("Launching countdown",time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))t = Thread(target=countdown,args=(5,started_evt))t.start()started_evt.wait()print("countdown is running",time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
结果:
C:\Python34\python.exe D:/kamil/Documents/py/process/Event_test.pyLaunching countdown 2016-03-23 16:03:28countdown starting 2016-03-23 16:03:28T-time_kamil: 5countdown is running 2016-03-23 16:03:28T-time_kamil: 4T-time_kamil: 3T-time_kamil: 2T-time_kamil: 1Process finished with exit code 0
Condition
如果一个线程需要不停重复的使用event对象,最好使用condition对象实现一个周期定时器,每当定时器超时的时候,其他线程都可以检测到:
#!/usr/bin/env python# encoding: utf-8"""@author: 侠之大者kamil@file: event_test2.py@time: 2016/3/23 14:45"""import time,threadingclass PeriodicTimer: def __init__(self,interval): self._interval = interval self._flag = 0 self._cv = threading.Condition()#使用Condition对象可以在某些事件触发或者达到特定的条件后才处理数据 def start(self): t = threading.Thread(target=self.run) t.daemon = True#Daemon线程表明整个Python主程序只有在Daemon子线程运行时可以退出. t.start() def run(self): while True: time.sleep(self._interval) with self._cv: self._flag ^=1 self._cv.notify_all() def wait_for_tick(self): with self._cv: last_flag = self._flag while last_flag == self._flag: self._cv.wait()ptimer = PeriodicTimer(5)ptimer.start()def countdown(nticks): while nticks > 0 : ptimer.wait_for_tick() print("t_time",nticks) nticks -= 1def countup(last): n = 0 while n < last: ptimer.wait_for_tick() print("counting",n) n +=1threading.Thread(target=countdown,args=(6,)).start()threading.Thread(target=countup,args=(3,)).start()
结果:
C:\Python34\python.exe D:/kamil/Documents/py/process/event_test2.pyt_time 6counting 0t_time 5counting 1t_time 4counting 2t_time 3t_time 2t_time 1Process finished with exit code 0
如上文中event在为真后,所有等待的进程都要开始,如果只想唤起一个进程,那可以使用Condition 对象来替代