1. 程式人生 > 程式設計 >Python中使用threading.Event協調執行緒的執行詳解

Python中使用threading.Event協調執行緒的執行詳解

threading.Event機制類似於一個執行緒向其它多個執行緒發號施令的模式,其它執行緒都會持有一個threading.Event的物件,這些執行緒都會等待這個事件的“發生”,如果此事件一直不發生,那麼這些執行緒將會阻塞,直至事件的“發生”。

對此,我們可以考慮一種應用場景(僅僅作為說明),例如,我們有多個執行緒從Redis佇列中讀取資料來處理,這些執行緒都要嘗試去連線Redis的服務,一般情況下,如果Redis連線不成功,在各個執行緒的程式碼中,都會去嘗試重新連線。

如果我們想要在啟動時確保Redis服務正常,才讓那些工作執行緒去連線Redis伺服器,那麼我們就可以採用threading.Event機制來協調各個工作執行緒的連線操作:

主執行緒中會去嘗試連線Redis服務,如果正常的話,觸發事件,各工作執行緒會嘗試連線Redis服務。

為此,我們可以寫下如下的程式:

import threading
import time
import logging
 
logging.basicConfig(level=logging.DEBUG,format='(%(threadName)-10s) %(message)s',)
 
def worker(event):
  logging.debug('Waiting for redis ready...')
  event.wait()
  logging.debug('redis ready,and connect to redis server and do some work [%s]',time.ctime())
  time.sleep(1)
 
readis_ready = threading.Event()
t1 = threading.Thread(target=worker,args=(readis_ready,),name='t1')
t1.start()
 
t2 = threading.Thread(target=worker,name='t2')
t2.start()
 
logging.debug('first of all,check redis server,make sure it is OK,and then trigger the redis ready event')
time.sleep(3) # simulate the check progress 
readis_ready.set()

執行這個程式:

(t1    ) Waiting for redis ready...
(t2    ) Waiting for redis ready...
(MainThread) first of all,and then trigger the redis ready event
(t2    ) redis ready,and connect to redis server and do some work [Wed Nov 5 12:45:03 2014]
(t1    ) redis ready,and connect to redis server and do some work [Wed Nov 5 12:45:03 2014]

t1和t2執行緒開始的時候都阻塞在等待redis伺服器啟動的地方,一旦主執行緒確定了redis伺服器已經正常啟動,那麼會觸發redis_ready事件,各個工作執行緒就會去連線redis去做相應的工作。

threading.Event的wait方法還接受一個超時引數,預設情況下如果事件一直沒有發生,wait方法會一直阻塞下去,而加入這個超時引數之後,如果阻塞時間超過這個引數設定的值之後,wait方法會返回。

對應於上面的應用場景,如果Redis伺服器一致沒有啟動,我們希望子執行緒能夠列印一些日誌來不斷地提醒我們當前沒有一個可以連線的Redis服務,我們就可以通過設定這個超時引數來達成這樣的目的:

import threading
import time
import logging
 
logging.basicConfig(level=logging.DEBUG,)
 
def worker(event):
  while not event.is_set():
    logging.debug('Waiting for redis ready...')
    event.wait(1)
  logging.debug('redis ready,and then trigger the redis ready event')
time.sleep(3) # simulate the check progress 
readis_ready.set()

與前面的無限阻塞版本唯一的不同就是,我們在工作執行緒中加入了一個while迴圈,直到redis_ready事件觸發之後才會結束迴圈,wait方法呼叫會在1秒的超時後返回,這樣,我們就可以看到各個工作執行緒在系統啟動的時候等待redis_ready的同時,會記錄一些狀態資訊。

以下是這個程式的執行結果:

(t1    ) Waiting for redis ready...
(t2    ) Waiting for redis ready...
(MainThread) first of all,and then trigger the redis ready event
(t2    ) Waiting for redis ready...
(t1    ) Waiting for redis ready...
(t2    ) Waiting for redis ready...
(t1    ) Waiting for redis ready...
(t2    ) redis ready,and connect to redis server and do some work [Wed Nov 5 13:55:46 2014]
(t1    ) redis ready,and connect to redis server and do some work [Wed Nov 5 13:55:46 2014]

這樣,我們就可以在等待Redis服務啟動的同時,看到工作執行緒里正在等待的情況。

以上這篇Python中使用threading.Event協調執行緒的執行詳解就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。