add by zhj: 之前只知道在Queue的實現中使用了Condition對象,可以實現生產者消費者功能,但具體怎麼使用Condition還是一知半解,看了這篇文章,終於懂了。很多事情往往一時看不明白,看得多了,某一天就突然明白了。
原文:https://blog.csdn.net/ckk727/article/details/99950843
作者:二十七º
一、Condition類提供的方法
__init__(self,lock=None)
1)從Condition類的構造方法可以看出,Condition類總是與一個鎖相關聯。在創建一個Condition類的同時就應該傳入Condition類需要綁定的Lock對象;
2)另外,如果不指定lock參數,那麼Python會自動創建一個與之綁定的Lock對象。
2. acquire方法
acquire(timeout)
調用Condition類關聯的Lock/RLock的acquire()方法。
3. release方法
release()
調用Condition類關聯的Lock/RLock的release()方法。
4. wait方法
wait(timeout)
1)線程掛起,直到收到一個notify通知或者等待時間超出timeout纔會被喚醒;
2)注意:wait()必須在已獲得Lock的前提下調用,否則會引起RuntimeError錯誤。
5. notify方法
notify(n=1)
1)喚醒在Condition的waiting池中的n(參數n可設置,默認爲1)個正在等待的線程並通知它,受到通知的線程將自動調用acquire()方法嘗試加鎖;
2)如果waiting池中有多個線程,隨機選擇n個喚醒;
3)必須在已獲得Lock的前提下調用,否則將引發錯誤。
notify_all()
喚醒waiting池中的等待的所有線程並通知它們。
二、實例詳解
生產者消費者問題
問題:
假設有一羣生產者(Producer)和一羣消費者(Consumer)通過一個市場來交互產品。生產者的”策略“是如果市場上剩餘的產品少於500個,那麼就生產50個產品放到市場上;而消費者的”策略“是如果市場上剩餘產品的數量多於100個,那麼就消費10個產品。
代碼:
import threading from time import sleep #商品 product = 500 #條件變量 con = threading.Condition(threading.Lock()) #生產者類 #繼承Thread類 class Producer(threading.Thread): def __init__(self,name): super().__init__() self.name = name def run(self): global product while True: #如果獲得了鎖 if con.acquire(): #處理產品大於等於500和小於500的情況 if product >= 500: #如果大於等於500,Producer不需要額外操作,於是掛起 con.wait() else: product += 50 message = self.name + " produced 50 products." print(message) #處理完成,發出通知告訴Consumer con.notify() #釋放鎖 con.release() sleep(1) #消費者類 #繼承Thread類 class Consumer(threading.Thread): def __init__(self,name): super().__init__() self.name = name def run(self): global product while True: #如果獲得了鎖 if con.acquire(): #處理product小於等於100和大於100的兩種情況 if product <= 100: #如果小於等於100,Consumer不需要額外操作,於是掛起 con.wait() else: product -= 10 message = self.name + " consumed 10 products." print(message) #處理完成,發出通知告訴Producer con.notify() #釋放鎖 con.release() sleep(1) def main(): #創建兩個Producer for i in range(2): p = Producer('Producer-%d'%i) p.start() #創建三個Consumer for i in range(3): c = Consumer('Consumer-%d'%i) c.start() if __name__ == '__main__': main()
運行結果:
Consumer-0 consumed 10 products. Consumer-1 consumed 10 products. Consumer-2 consumed 10 products. Producer-0 produced 50 products. Consumer-0 consumed 10 products. Consumer-1 consumed 10 products. Consumer-2 consumed 10 products. Producer-0 produced 50 products. Consumer-1 consumed 10 products. Consumer-0 consumed 10 products. Consumer-2 consumed 10 products. Consumer-1 consumed 10 products. ......
一、Condition類提供的方法構造方法:
__init__(self,lock=None)11)從Condition類的構造方法可以看出,Condition類總是與一個鎖相關聯。在創建一個Condition類的同時就應該傳入Condition類需要綁定的Lock對象;
2)另外,如果不指定lock參數,那麼Python會自動創建一個與之綁定的Lock對象。
acquire(timeout)1調用Condition類關聯的Lock/RLock的acquire()方法。
release()1調用Condition類關聯的Lock/RLock的release()方法。
wait(timeout)11)線程掛起,直到收到一個notify通知或者等待時間超出timeout纔會被喚醒;
2)注意:wait()必須在已獲得Lock的前提下調用,否則會引起RuntimeError錯誤。
notify(n=1)11)喚醒在Condition的waiting池中的n(參數n可設置,默認爲1)個正在等待的線程並通知它,受到通知的線程將自動調用acquire()方法嘗試加鎖;
2)如果waiting池中有多個線程,隨機選擇n個喚醒;
3)必須在已獲得Lock的前提下調用,否則將引發錯誤。
notify_all()1喚醒waiting池中的等待的所有線程並通知它們。
二、實例詳解生產者消費者問題
問題:
假設有一羣生產者(Producer)和一羣消費者(Consumer)通過一個市場來交互產品。生產者的”策略“是如果市場上剩餘的產品少於500個,那麼就生產50個產品放到市場上;而消費者的”策略“是如果市場上剩餘產品的數量多於100個,那麼就消費10個產品。
代碼:
import threadingfrom time import sleep
#商品product = 500#條件變量con = threading.Condition(threading.Lock())
#生產者類#繼承Thread類class Producer(threading.Thread): def __init__(self,name): super().__init__() self.name = name def run(self): global product while True: #如果獲得了鎖 if con.acquire(): #處理產品大於等於500和小於500的情況 if product >= 500: #如果大於等於500,Producer不需要額外操作,於是掛起 con.wait() else: product += 50 message = self.name + " produced 50 products." print(message) #處理完成,發出通知告訴Consumer con.notify() #釋放鎖 con.release() sleep(1)#消費者類#繼承Thread類class Consumer(threading.Thread): def __init__(self,name): super().__init__() self.name = name def run(self): global product while True: #如果獲得了鎖 if con.acquire(): #處理product小於等於100和大於100的兩種情況 if product <= 100: #如果小於等於100,Consumer不需要額外操作,於是掛起 con.wait() else: product -= 10 message = self.name + " consumed 10 products." print(message) #處理完成,發出通知告訴Producer con.notify() #釋放鎖 con.release() sleep(1) def main(): #創建兩個Producer for i in range(2): p = Producer('Producer-%d'%i) p.start() #創建三個Consumer for i in range(3): c = Consumer('Consumer-%d'%i) c.start()
if __name__ == '__main__': main()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869運行結果:
Consumer-0 consumed 10 products.Consumer-1 consumed 10 products.Consumer-2 consumed 10 products.Producer-0 produced 50 products.Consumer-0 consumed 10 products.Consumer-1 consumed 10 products.Consumer-2 consumed 10 products.Producer-0 produced 50 products.Consumer-1 consumed 10 products.Consumer-0 consumed 10 products.Consumer-2 consumed 10 products.Consumer-1 consumed 10 products.......————————————————版權聲明:本文爲CSDN博主「二十七º」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/ckk727/article/details/99950843