Event 準系統介紹
http://blog.sina.com.cn/s/blog_4b5039210100exlg.html
vent對象實現了簡單的線程通訊機制,它提供了設定訊號,清楚訊號,等待等用於實現線程間的通訊。
1 設定訊號
使用Event的set()方法可以設定Event對象內部的訊號標誌為真。Event對象提供了isSet()方法來判斷其內部訊號標誌的狀態。當使用event對象的set()方法後,isSet()方法返回真
2 清除訊號
使用Event對象的clear()方法可以清除Event對象內部的訊號標誌,即將其設為假,當使用Event的clear方法後,isSet()方法返回假
3 等待
Event對象wait的方法只有在內部訊號為真的時候才會很快的執行並完成返回。當Event對象的內部訊號標誌位假時,則wait方法一直等待到其為真時才返回。
本執行個體解決這樣的需求:A 線程會每隔一段時間更新一塊記憶體地區, 如一個字典 dict.B 線程會不斷讀 dict.那麼為了防止 B 線程讀 dict 時 A 線程在做更新, 以及 A 線程在做更新時 B 線程在讀, 需要使用 Event 來解決此問題。A 線程在更新時, 首先檢查 B 線程是否在讀, 若在讀, A 線程等待. B 線程每次讀的時候會首先檢查 A 線程是否在更新, 在更新時 B 不讀, 略過, 沒有更新時, B 線程讀 dict, 讀之前設定一個訊號量, 讀完通知 A 線程更新。A 線程更新時, 可以設定兩個記憶體地區, dict_new 儲存新值dict 儲存舊值在更新時只需要做指標賦值即可, 這樣會很快.import sysimport threadingimport timeevent1 = threading.Event()event2 = threading.Event()event1.set() # 初始內部標誌為真.event2.set()class RelTweet(threading.Thread): #The timer class is derived from the class threading.Thread def __init__(self, num): threading.Thread.__init__(self) self.thread_num = num self.thread_stop = False self.dataIsUsed = 0 self.dataUpdate = 0 # 0-not update, 1-updated, 2-updating, condition variable self.dict = {} # init dict self.dataUpdate = 1 self.dict["qq"] = 100 def run(self): #Overwrite run() method, put what you want the thread do here print '[thread] Thread %d running.' %(self.thread_num) i = 0 while not self.thread_stop: time.sleep(3) # updtae interval is 3 seconds. if self.thread_stop == False: # 停止當前線程 # break
if not event2.isSet(): # 若訊號 event2 為假, 一直等待. event2.wait() # 當前線程等待, 當 event2 被設定為真 (調用 set 方法時). 當前線程被喚醒. 繼續執行 print "update thread wait" if self.thread_stop == False: # 停止當前線程 # break print "[thread] updating dict"
event1.clear() i += 1 self.dict["qq"] = i time.sleep(3) # update used 3 seconds.
event1.set() print "[thread] updating dict finish" def stop(self): self.thread_stop = True def test(): thread1 = RelTweet(1) print "[main] thread start" thread1.start() print "[main] running" loop = 1000 while True: try: if loop <= 0: break if event1.isSet(): event2.clear() # 設定內部標誌為假 time.sleep(0.008) print thread1.dict["qq"] event2.set() # 設定內部標誌為真,喚醒等待線程 print "data is not used" loop -= 1 except Exception, e: print e thread1.stop() sys.exit(1) thread1.stop() print "[main] main is finished" return if __name__ == '__main__': test()