python多線程編程-queue模塊和生產者-消費者問題
阿新 • • 發佈:2018-04-20
獲取 區別 from html als 最大值 python3.6 .py python
摘錄python核心編程
本例中演示生產者-消費者模型:商品或服務的生產者生產商品,然後將其放到類似隊列的數據結構中。生產商品中的時間是不確定的,同樣消費者消費商品的時間也是不確定的。
使用queue模塊(python2.x版本中,叫Queue)來提供線程間通信的機制,從而讓線程之間可以分享數據。具體而言,就是創建一個隊列,讓生產者(線程)在其中放入新的商品,而消費者(線程)消費這些商品。
下表是queue模塊的部分屬性:
屬性 | 描述 |
queue模塊的類 | |
Queue(maxsize=0) | 創建一個先入先出隊列。如果給定最大值,則在隊列沒有空間時阻塞;否則,為無限隊列 |
LifoQueue(maxsize=0) |
創建一個後入先出隊列。如果給定最大值,則在隊列沒有空間時阻塞;否則,為無限序列 |
PriorityQueue(maxsize=0) | 創建一個優先級隊列。如果給定最大值,則在隊列沒有空間時阻塞;否則,為無限序列 |
queue異常 | |
Empty | 當對空隊列調用get*()方法時拋出異常 |
Full | 當對已滿的隊列調用put*()方法時拋出異常 |
queue對象方法 | |
qsize() | 返回隊列大小。(由於返回隊列大小時可能被其他線程修改,所以該值為近似值) |
empty() | 如果隊列為空,則返回True,否則返回False |
full() | 如果隊列已滿,則返回True,否則返回False |
put(item,block=True,timeout=None) | 將item放入隊列。如果block為True(默認值),且timeout為None,則在有可用空間之前阻塞;如果timeout為正值,最多阻塞timeout秒;如果block為False,則拋出Empty異常 |
put_nowait(item) | 和put(item,False)效果相同 |
get(block=True,timeout=None) | 從隊列上取得元素。如果給定了block(非0),則一直阻塞直到有可用的元素為止 |
get_nowait() | 和get(False)效果想用 |
task_done() | 用於表示隊列中的某個元素已執行完成,該方法會被下面的join()使用 |
join() | 在隊列中所有元素執行完畢並調用上面的task_done()信號前,保持阻塞。 |
下面的prodcons.py腳本中使用了queue對象實現了生產者-消費者場景,隨機生產或消費商品,且生產者和消費者獨立、並發的執行線程。註意,這裏使用了在之前章節中改寫的MyThread類。
#python 3.6 from random import randint from time import sleep from queue import Queue from myThread import MyThread #將一個對象放入隊列中 def writeQ(queue): print(‘正在為隊列生產………‘) queue.put(‘商品‘,1) print(‘當前商品總數:‘,queue.qsize()) #消費隊列中的一個對象 def readQ(queue): val = queue.get(1) print(‘正在從隊列中消費商品……消費後還剩余商品:‘,queue.qsize()) #模仿生產者。 def writer(queue,loops): for i in range(loops): writeQ(queue) sleep(randint(1,3))#writer的睡眠時間一般比reader短,是為了阻礙 reader從空隊列中獲取對象,換句話說就是使得輪到reader執行時,已存在可消費對象的可能性更大。 #模仿消費者 def reader(queue,loops): for i in range(loops): readQ(queue) sleep(randint(2,5)) funcs = [writer,reader] nfuncs = range(len(funcs)) def main(): nloops = randint(2,5)#randint 和randrange類似,區別在於,randrange是半開半閉區間,而randint是閉區間 q = Queue(32) threads = []#模擬線程池 for i in nfuncs: t = MyThread(funcs[i],(q,nloops),funcs[i].__name__)#創建線程 threads.append(t) for i in nfuncs: threads[i].start() #開始執行線程 for i in nfuncs: threads[i].join() print(‘結束‘) if __name__ == ‘__main__‘: main()
執行效果類似:
PS C:\Users\WC> python E:\Python3.6.3\workspace\prodcons.py 開始執行 writer 在: Thu Apr 19 21:06:22 2018 正在為隊列生產……… 開始執行 reader 在: Thu Apr 19 21:06:22 2018 當前商品總數: 1 正在從隊列中消費商品……消費後還剩余商品: 0 正在為隊列生產……… 當前商品總數: 1 正在從隊列中消費商品……消費後還剩余商品: 0 正在為隊列生產……… 當前商品總數: 1 正在從隊列中消費商品……消費後還剩余商品: 0 正在為隊列生產……… 當前商品總數: 1 正在為隊列生產……… 當前商品總數: 2 writer 結束於: Thu Apr 19 21:06:30 2018 正在從隊列中消費商品……消費後還剩余商品: 1 正在從隊列中消費商品……消費後還剩余商品: 0 reader 結束於: Thu Apr 19 21:06:39 2018 結束
python多線程編程-queue模塊和生產者-消費者問題