-
生產者和消費者模型
在多執行緒開發的過程中有可能遇到這樣一種情形:
有一部分執行緒負責生產一些資料,有一部分負責處理一些資料,把製造資料的那一部分執行緒叫做生產者,處理資料的那一部分執行緒叫做消費者,如果生產者生產的資料速度大於消費者處理資料的速度,那麼生產者就必須要等待消費者處理完成才能繼續生產,同樣消費者處理資料的速度大於生產者,那消費者就要等待生產者,為了解決這個問題,於是引入了生產者和消費者模型。
生產者和消費者模型:
生產者 ----> 緩衝區(倉庫) ----> 消費者 複製程式碼
生產者和消費者不直接通訊,生產者生產的資料丟給緩衝區,消費者拿資料則是向緩衝區拿。
可以將生產者和消費者模型想象成寄信:
- 發件人就是生產者,寫信
- 郵箱就是緩衝區,將信放入郵箱。
- 郵遞員從郵箱中拿出信,進行後續的處理就是消費者
要實現這樣的模型,需要用到佇列,佇列就是生產者和消費者之間的緩衝區。
-
queues模組
佇列,又稱為佇列(queue),是先進先出(FIFO, First-In-First-Out)的線性表。在具體應用中通常用連結串列或者陣列來實現。佇列只允許在後端(稱為rear)進行插入操作,在前端(稱為front)進行刪除操作。 - 維基百科
queues模組實現多生產者,多消費者佇列。
-
queue.Queue(maxsize=0)
FIFO(先進先出) 佇列的構造方法。 maxsize 是一個整數,它設定了可以放入佇列中的專案數量的上限。一旦達到此大小,插入就會阻塞,直到佇列項被消耗。如果 maxsize 小於或等於零,佇列大小是無限的。
-
queue.LifoQueue(maxsize=0)
LIFO(後進先出) 佇列的構造方法。 maxsize 是一個整數,它設定了可以放入佇列中的專案數量的上限。一旦達到此大小,插入就會阻塞,直到佇列項被消耗。如果 maxsize 小於或等於零,佇列大小是無限的。
-
queue.PriorityQueue(maxsize=0)
優先順序佇列的建構函式。 maxsize 是一個整數,它設定了可以放入佇列中的專案數量的上限。一旦達到此大小,插入就會阻塞,直到佇列項被消耗。如果 maxsize 小於或等於零,佇列大小是無限的。
存放資料的格式: Queue.put((priority_number,data)),priority_number越小,優先順序越高,data代表存入的值
通過例子看這三種佇列的不同之處:
import queue # 先進先出 q_FIFO = queue.Queue(3) q_FIFO.put(1) # 存第一個資料 q_FIFO.put(2) # 存第二個資料 q_FIFO.put(3) # 存第二個資料 print('取第一個資料', q_FIFO.get()) print('取第二個資料', q_FIFO.get()) print('取第三個資料', q_FIFO.get()) 複製程式碼
結果:
拿出的資料的順序和存放進去資料的順序是一樣的
# 後進先出 q_LIFO = queue.LifoQueue(3) q_LIFO.put(1) # 存第一個資料 q_LIFO.put(2) # 存第二個資料 q_LIFO.put(3) # 存第二個資料 print('取第一個資料', q_LIFO.get()) print('取第二個資料', q_LIFO.get()) print('取第三個資料', q_LIFO.get()) 複製程式碼
結果:
越後放進去的資料越先取出來
# 優先順序佇列 q_Priority = queue.PriorityQueue(3) q_Priority.put((10, '我的優先順序是10')) # 存第一個資料 q_Priority.put((-1, '我的優先順序是-1')) # 存第二個資料 q_Priority.put((1, '我的優先順序是10')) # 存第三個資料 print('取第一個資料', q_Priority.get()) print('取第二個資料', q_Priority.get()) print('取第三個資料', q_Priority.get()) 複製程式碼
結果:
它根據傳入的(priority_number,data)格式的資料中的priority_number決定優先順序的大小,priority_number越小優先順序越高。
-
-
Queue,LifoQueue,PriorityQueue佇列提供的方法
-
Queue.qsize()
返回當前佇列的長度,但是結果並不可靠,原因是多執行緒情況下,有可能在Queue.qsize()拿到的結果是1,但是其他執行緒有可能在當前執行緒獲取資料之前已經拿走資料了,這就會導致當前執行緒拿資料的時候佇列的長度變成0,所以Queue.qsize的結果是不可靠的。
例子:
import queue from threading import Thread import time # 建立佇列 q = queue.Queue(3) # 消費者1 def print_something(): q_size = q.qsize() if q_size: print('佇列長度為:%d' % q_size) time.sleep(1) # 等一秒再處理資料 print('消費者1', q.get()) q.task_done() # task_done方法等下會說,可理解為通知佇列當前獲取到的資料已處理完畢 # 生產者1 def put_something(): q.put(1) print('生產者1') # 消費者2 def early_treatment(): print('消費者2', q.get()) q.task_done() t1 = Thread(target=put_something) t2 = Thread(target=print_something) t3 = Thread(target=early_treatment) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() 複製程式碼
結果:
因為消費者1等了一秒才開始處理資料,另一個執行緒的消費者2則是立即處理資料,所以資料當消費者1處理資料的時候,佇列已經空了,沒有資料了,消費者1就只能一直等待。
-
Queue.empty()
如果佇列為空,返回 True,否則返回 False。它和qsize一樣,結果也是不可靠的。
-
Queue.full()
如果佇列已滿,返回 True,否則返回 False。它和qsize一樣,結果也是不可靠的。
-
Queue.put(item, block=True, timeout=None)
將 item 放入佇列。
- item:放入佇列的資料
- block:是否阻塞
- timeout:阻塞等待時間,必須是非負數或者None
例子:
- block為True且timeout為None,如果佇列滿了,那麼會一直等待,直到佇列有空位再進行放入。
import queue import datetime # 建立佇列 q = queue.Queue(3) # block為True且timeout為None try: for i in range(4): q.put(i) old_time = datetime.datetime.now() except queue.Full: new_time = datetime.datetime.now() print('阻塞等待時間:%s秒' % (new_time - old_time).seconds) 複製程式碼
- block為True且timeout為0,如果佇列滿了,立即丟擲queue.Full異常。
import queue import datetime # 建立佇列 q = queue.Queue(3) # block為True且timeout為0 try: for i in range(4): q.put(i, timeout=0) old_time = datetime.datetime.now() except queue.Full: new_time = datetime.datetime.now() print('阻塞等待時間:%s秒' % (new_time - old_time).seconds) 複製程式碼
結果:
- block為True且timeout為正數,如果佇列滿了,會等待timeout中傳入的秒數,如果超過了timeout中傳入的秒數,丟擲queue.Full異常。
import queue import datetime # 建立佇列 q = queue.Queue(3) # block為True且timeout為正數 try: for i in range(4): q.put(i, timeout=3) old_time = datetime.datetime.now() except queue.Full: new_time = datetime.datetime.now() print('阻塞等待時間:%s秒' % (new_time - old_time).seconds) 複製程式碼
結果:
- block為False,佇列滿了會立即丟擲queue.Full異常。
-
Queue.put_nowait(item)
相當於 put(item, block=False)。
-
Queue.get(block=True, timeout=None)
從佇列中刪除並返回專案。block和timeout引數的含義和put方法相同,不過執行的操作是拿出不是放入。當佇列為空時,繼續get會丟擲queue.Empty異常。
-
Queue.get_nowait()
相當於 get(False)。
-
Queue.task_done()
通知佇列當前使用get獲取的任務已完成。
-
Queue.join()
阻塞,直到佇列中的所有任務都被獲取和處理。
-
-
簡單的生產者消費者模型
-
先生產後消費
import threading import queue import random def producer(): """ 模擬生產者 """ for i in range(10): q.put("%s元" % random.randint(1, 100)) print("等待所有的錢被取走...") q.join() print("所有的錢被取完了...") def consumer(n): """ 模擬消費者 """ while q.qsize() > 0: print("%s 取到" % n, q.get()) q.task_done() q = queue.Queue() p1 = threading.Thread(target=producer) p1.start() c1 = consumer("allen") 複製程式碼
-
邊生產邊消費
import threading import queue import random import time def producer(): """ 模擬生產者 """ while True: time.sleep(random.randint(1, 5)) data = random.randint(1, 100) q.put("%s元" % data) print('存入:%s元' % data) def consumer(n): """ 模擬消費者 """ while True: time.sleep(random.randint(1, 5)) data = q.get() print("%s 取到" % n, data) q.task_done() q = queue.Queue() names = ['allen', 'jack'] p1 = threading.Thread(target=producer) p1.start() for name in names: c = threading.Thread(target=consumer, args=(name,)) c.start() 複製程式碼
-
Python學習筆記 - queue
相關文章
- C++ 學習筆記之——STL 庫 queueC++筆記
- Python學習筆記Python筆記
- 【學習筆記】python筆記Python
- python學習筆記(1Python筆記
- Effective Python學習筆記Python筆記
- python——Matplotlib學習筆記Python筆記
- python學習筆記4Python筆記
- Python學習筆記 - asyncioPython筆記
- Python 學習筆記(一)Python筆記
- Python學習筆記 - aiohttpPython筆記AIHTTP
- python學習筆記(二)Python筆記
- Python學習筆記(2)Python筆記
- python——numpy學習筆記Python筆記
- Python學習筆記(三)Python筆記
- Python學習筆記|Python之程式Python筆記
- 【拉勾教育】學習筆記之集合類庫(Iterator、foreach、List、Queue)筆記
- Python學習筆記—程式碼Python筆記
- Python學習筆記 - 閉包Python筆記
- Python學習筆記 - 作用域Python筆記
- Python學習筆記 - 變數Python筆記變數
- Python學習筆記 - 多程式Python筆記
- Python學習筆記 - time, datetimePython筆記
- Python學習筆記 - if語句Python筆記
- Python學習筆記——turtle庫Python筆記
- python-pygame學習筆記PythonGAM筆記
- Python基礎學習筆記Python筆記
- 字典--Python學習筆記(五)Python筆記
- Python學習筆記|Python之yield理解Python筆記
- Python學習筆記|Python之索引迭代Python筆記索引
- Python學習筆記|Python之特殊方法Python筆記
- [寒假學習筆記](二)Python初學筆記Python
- 【Python學習】學習筆記 14-15 字串Python筆記字串
- python基礎學習筆記(一)Python筆記
- Python學習筆記 - 裝飾器Python筆記
- Python學習筆記 - lambda表示式Python筆記
- Python學習筆記 - 字串,數字Python筆記字串
- python爬蟲—學習筆記-4Python爬蟲筆記
- python爬蟲—學習筆記-2Python爬蟲筆記