threading.Timer的作用
官方給的定義是:
"""Call a function after a specified number of seconds:
t = Timer(30.0, f, args=None, kwargs=None)
t.start()
t.cancel() # stop the timer's action if it's still waiting
"""
意思是:
在一個特定的秒數之后調用一個函數,使用方法是創建一個Timer實例,然后start()啟動線程,如果在線程調用傳入的函數之前可以使用cancel進行取消。
threading.Timer源碼分析
1 class Timer(Thread): # 繼承自Thread類 2 """Call a function after a specified number of seconds: 3 4 t = Timer(30.0, f, args=None, kwargs=None) 5 t.start() 6 t.cancel() # stop the timer's action if it's still waiting 7 8 """ 9 10 def __init__(self, interval, function, args=None, kwargs=None): # 初始化的時候傳參是延遲時間、調用的函數,函數的可變位置參數、函數的可變關鍵字參數 11 Thread.__init__(self) # 調用Thread類初始化配置實例 12 self.interval = interval # 在使用Thread類初始化配置實例之后再額外的增加interval屬性 13 self.function = function # 同理再額外的增加function屬性 14 self.args = args if args is not None else [] # 如果args不是空的話就使用args,如果是空就給一個空list 15 self.kwargs = kwargs if kwargs is not None else {} # 同理,kwargs不是空的就是kwargs,如果是空就給一個空字典 16 self.finished = Event() # 再添加一個屬性finished,是一個Event類的實例,這里知道Event類的實例用法就知道它在這里要怎么用了 17 18 def cancel(self):
"""如果finished屬性還沒有被set,即函數function還沒有被調用的之前阻止,因為下面函數調用之前會判斷finished是否被set了,所以這里趕在調用之前注定set就能夠阻止后面的調用。""" 19 """Stop the timer if it hasn't finished yet.""" 20 self.finished.set() 21 22 def run(self): # 繼承自Thread類,並且重寫了Thread類,我們分析Thread類的源碼會發現,start()方法會主動調用self.run(),
# 我們Timer類沒有實現start()方法,這樣Timer類實例在執行start()的時候會跑到父類Thread上,然后調用父類的start,
# 在父類的start()方法中會有一句self.run()來調用工作線程中的函數,這里self是Timer的實例,所以,這里可以重寫run就可以設定run的時間了。
23 self.finished.wait(self.interval) # 這里使用Event類的實例的wait方法,等待了我們設定的self.interval時間,然后關鍵點是下面一句 24 if not self.finished.is_set(): # 這一句是關鍵點,檢查一下是否被set了,如果沒有被set了就調用傳入的函數,如果被set了有兩種情況:
# 第一種情況是在self.finished.wait(self.interval)的期間,我們調用cancel主動提前set了;
# 第二種情況是已經start()過一次了,這里就不能再進行start了這樣就和父類的保持了一致:即一個線程只能夠start一次
25 self.function(*self.args, **self.kwargs) 26 self.finished.set() # 調用完成后set,即便之前已經被set了,這里還可以被set,因為Event實例可以被set多次。