Python 多執行緒小技巧:比 time.sleep 更好用的暫停寫法!
我們知道,在 Python 裡面可以使用time.sleep來讓程式碼暫停一段時間,例如:
import time
print('...部分程式碼...')
time.sleep(5)
print('...剩下的程式碼...')
程式首先打印出...部分程式碼...,然後等待5秒鐘,再打印出...剩下的程式碼...。
現在大家想一想,有沒有什麼辦法,在不使用time.sleep的情況下,讓程式暫停5秒?
你可能會說,用requests訪問一個延遲5秒的網址、或者用遞迴版演算法計算斐波那契數列第36位……這些奇技淫巧。
不過今天我說的,是另外一個東西,threading模組裡面的Event。
我們來看看它的用法:
import threading
event = threading.Event()
print('...部分程式碼...')
event.wait(5)
print('...剩下的程式碼...')
這樣一來,程式首先打印出...部分程式碼...,然後等待5秒鐘,再打印出...剩下的程式碼...。
功能看起來跟time.sleep沒什麼區別,那為什麼我要特別提到它呢?因為在多執行緒裡面,它比time.sleep更有用。我們來看一個例子:
import threading
class Checker(threading.Thread):
def __init__(self, event):
super().__init__()
self.event = event
def run(self):
while not self.event.is_set():
print('檢查 redis 是否有資料')
time.sleep(60)
trigger_async_task()
event = threading.Event()
checker = Checker(event)
checker.start()
if user_cancel_task():
event.set()
我來解釋一下這段程式碼的意思。在主執行緒裡面,我呼叫trigger_async_task()觸發了一個非同步任務。這個任務多久完成我並不清楚。但是這個任務完成以後,它會往 Redis 裡面傳送一條訊息,只要 Redis 有這個訊息了,我就知道它完成了。所以我要建立一個 checker 子執行緒,每60秒去 Redis裡面檢查任務是否完成。如果沒有完成,就暫停60秒,然後再檢查。
但某些情況下,我不需要等待了,例如使用者主動取消了任務。這個時候,我就想提前結束這個 checker 子執行緒。
但是我們知道,執行緒是不能從外面主動殺死的,只能讓它自己退出。所以當我執行event.set()後,子執行緒裡面self.event.is_set()就會返回 False,於是這個迴圈就不會繼續執行了。
可是,如果某一輪迴圈剛剛開始,我在主執行緒裡面呼叫了event.set()。此時,子執行緒還在time.sleep中,那麼子執行緒需要等待60秒才會退出。
但如果我修改一下程式碼,使用self.event.wait(60):
import threading
class Checker(threading.Thread):
def __init__(self, event):
super().__init__()
self.event = event
def run(self):
while not self.event.is_set():
print('檢查 redis 是否有資料')
self.event.wait(60)
trigger_task()
event = threading.Event()
checker = Checker(event)
checker.start()
if user_cancel_task():
event.set()
那麼,即便self.event.wait(60)剛剛開始阻塞,只要我在主執行緒中執行了event.set(),子執行緒裡面的阻塞立刻就會結束。於是子執行緒立刻就會結束。不需要再白白等待60秒。
並且,event.wait()這個函式在底層是使用 C 語言實現的,不受 GIL 鎖的干擾。
以上就是本次分享的所有內容,想要了解更多 python 知識歡迎前往公眾號:Python 程式設計學習圈 ,傳送 “J” 即可免費獲取,每日干貨分享
- 位元組一面:Redis主節點宕機,如何處理?
- 如何使用 Redis 實現 “附近的人” 這個功能?
- 介紹一款能取代 Scrapy 的爬蟲框架 - feapder
- 直觀講解一下 RPC 呼叫和 HTTP 呼叫的區別!
- MySQL 億級資料分頁的優化
- Python 多執行緒小技巧:比 time.sleep 更好用的暫停寫法!
- Python面試官:請說說併發場景鎖怎麼用?
- Python如何非同步傳送日誌到遠端伺服器?
- Python 中的數字到底是什麼?
- 如何建立一個完美的 Python 專案?
- 詳解 Python 的二元算術運算,為什麼說減法只是語法糖?
- Python 為什麼沒有 main 函式?為什麼我不推薦寫 main 函式?
- Bug分析,假刪除導致文章釋出成功卻打不開的問題
- Python 進階:queue 佇列原始碼分析
- Python例項篇:自動操作Excel檔案(既簡單又特別實用)
- 誰說程式設計師不懂浪漫,當代碼遇到文學..
- Python 為什麼沒有 void 關鍵字?
- 程式語言中分號“;”的簡明歷史
- Python 什麼情況下會生成 pyc 檔案?
- 函式和方法的裝飾器