事件對象管理一個內部標誌,經過set()
方法將其設置爲True
,並使用clear()
方法將其設置爲False
。wait()
方法阻塞,直到標誌爲True
。該標誌初始爲False
。python
方法:
is_set()
當且僅當內部標誌爲True
時返回True
。安全
set()
將內部標誌設置爲True
。全部等待它成爲True
的線程都被喚醒。當標誌保持在True
的狀態時,線程調用wait()
是不會阻塞的。併發
clear()
將內部標誌重置爲False
。隨後,調用wait()
的線程將阻塞,直到另外一個線程調用set()
將內部標誌從新設置爲True
。線程
wait(timeout=None)
阻塞直到內部標誌爲真。若是內部標誌在wait()
方法調用時爲True
,則當即返回。不然,則阻塞,直到另外一個線程調用set()
將標誌設置爲True
,或發生超時。
該方法老是返回True
,除非設置了timeout
併發生超時。code
# -*- coding:utf-8 -*- import threading import time import queue event = threading.Event() goods = queue.Queue(5) num = 0 class Producer(threading.Thread): def run(self): global num while True: if goods.empty(): event.clear() for _ in range(5): goods.put('商品-' + str(num)) print('生產了商品-{0}.'.format(str(num))) num += 1 time.sleep(1) event.set() class Customer(threading.Thread): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.money = 7 def run(self): while self.money: event.wait() self.money -= 1 print('{0} 買了一個{1}.'.format( threading.current_thread().name, goods.get())) time.sleep(1) print('{0}沒錢了,回家.'.format(threading.current_thread().name)) if __name__ == '__main__': p = Producer(daemon=True) c1 = Customer(name='Alice') c2 = Customer(name='Bob') c2.start() p.start() c1.start() c1.join() c2.join()
運行結果:orm
生產了商品-0. 生產了商品-1. 生產了商品-2. 生產了商品-3. 生產了商品-4. Alice 買了一個商品-0. Bob 買了一個商品-1. Alice 買了一個商品-2. Bob 買了一個商品-3. Alice 買了一個商品-4. 生產了商品-5. 生產了商品-6. 生產了商品-7. 生產了商品-8. 生產了商品-9. Alice 買了一個商品-5. Bob 買了一個商品-6. Alice 買了一個商品-7. Bob 買了一個商品-8. 生產了商品-10. Alice 買了一個商品-9. 生產了商品-11. 生產了商品-12. 生產了商品-13. 生產了商品-14. Alice 買了一個商品-10. Bob 買了一個商品-11. Alice沒錢了,回家. Bob 買了一個商品-12. Bob 買了一個商品-13. Bob沒錢了,回家.
這裏會出現一種特殊狀況,當消費者線程較多時會大量出現:對象
生產了商品-0. 生產了商品-1. 生產了商品-2. 生產了商品-3. 生產了商品-4. Bob 買了一個商品-0. Alice 買了一個商品-1. Bob 買了一個商品-2. Alice 買了一個商品-3. Bob 買了一個商品-4. 生產了商品-5. # !!!!! Alice 買了一個商品-5. # !!!!! 生產了商品-6. 生產了商品-7. 生產了商品-8. 生產了商品-9. Bob 買了一個商品-6. Alice 買了一個商品-7. Alice 買了一個商品-8. Bob 買了一個商品-9. 生產了商品-10. 生產了商品-11. 生產了商品-12. 生產了商品-13. 生產了商品-14. Alice 買了一個商品-10. Bob 買了一個商品-11. Bob 買了一個商品-12. Alice 買了一個商品-13. Bob沒錢了,回家. Alice沒錢了,回家.
這是由於生產者在輪詢檢查商品是否爲空會有很小的延遲,在這個延遲中有消費者線程正好跑過了wait()
方法,而阻塞在了商品獲取這裏(商品使用了隊列,隊列是線程安全的,當隊列爲空時,get()方法會阻塞),因此當生產者開始執行的時候,這個消費者由於商品隊列裏有數據就被當即喚醒了。隊列