1. 程式人生 > >【python】詳解queue佇列

【python】詳解queue佇列

一、佇列的定義

佇列類似於一條管道,元素先進先出,進put(arg),取get( )。需要注意的是:佇列都是在記憶體中操作,程序退出,佇列清空,另外,佇列也是一個阻塞的形態。

二、佇列分類

佇列有很多種,但都依賴模組queue

佇列方式 特點
queue.Queue 先進先出佇列
queue.LifoQueue 後進先出佇列
queue.PriorityQueue 優先順序佇列
queue.deque 雙線佇列

三、佇列的方法

方法 用法說明
put 放資料,Queue.put( )預設有block=True和timeout兩個引數。當block=True時,寫入是阻塞式的,阻塞時間由timeout確定。當佇列q被(其他執行緒)寫滿後,這段程式碼就會阻塞,直至其他執行緒取走資料。Queue.put()方法加上 block=False 的引數,即可解決這個隱蔽的問題。但要注意,非阻塞方式寫佇列,當佇列滿時會丟擲 exception Queue.Full 的異常
get 取資料(預設阻塞),Queue.get([block[, timeout]])獲取佇列,timeout等待時間
empty 如果佇列為空,返回True,反之False
qsize 顯示佇列中真實存在的元素長度
maxsize 最大支援的佇列長度,使用時無括號
join 實際上意味著等到佇列為空,再執行別的操作
task_done 在完成一項工作之後,Queue.task_done()函式向任務已經完成的佇列傳送一個訊號
full 如果佇列滿了,返回True,反之False

四、單向佇列

import queue

q=queue.Queue(5)    #如果不設定長度,預設為無限長
print(q.maxsize)    #注意沒有括號
q.put(123)
q.put(456)
q.put(789)
q.put(100)
q.put(111)
q.put(233)
print(q.get())
print(q.get())

列印時候是阻塞的,因為建立了5個元素長度的佇列,但我put進去了6個,所以就阻塞了。如果少寫一個能顯示出正確的123。

import queue
    
q=queue.Queue(5)    #如果不設定長度,預設為無限長
print(q.maxsize)    #注意沒有括號
q.put(123)
q.put(456)
q.put(789)
q.put(100)
q.put(111)
print(q.get())
print(q.get())
-----------------------------------
5
123
456

print(q.get())
789
print(q.get())
100
print(q.get())
111

五、後進先出佇列

q = queue.LifoQueue()
q.put(12)
q.put(34)
print(q.get())
-------------
34

六、優先順序佇列

需要注意的是,優先順序佇列put的是一個元組,(優先順序,資料),優先順序數越小,級別越高

q = queue.PriorityQueue()
q.put((3,'aaaaa'))
q.put((3,'bbbbb'))
q.put((1,'ccccc'))
q.put((3,'ddddd'))
print(q.get())
print(q.get())
 --------------------------
(1, 'ccccc')
(3, 'aaaaa')

七、雙線佇列

q = queue.deque()
q.append(123)
q.append(456)
q.appendleft(780)
print(q)
print(q.pop())
print(q.popleft())
-----------------------------
deque([780, 123, 456])
456
780

八、生產消費者模型

解決什麼問題,使用場景
從下面圖中可以發現生產者和消費者之間用中間類似一個佇列一樣的東西串起來。這個佇列可以想像成一個存放產品的“倉庫”,生產者只需要關心這個“倉庫”,並不需要關心具體的消費者,對於生產者而言甚至都不知道有這些消費者存在。對於消費者而言他也不需要關心具體的生產者,到底有多少生產者也不是他關心的事情,他只要關心這個“倉庫”中還有沒有東西。這種模型是一種鬆耦合模型。這個模型的產生就是為了複用和解耦。比如常見的訊息框架(非常經典的一種生產者消費者模型的使用場景)ActiveMQ。傳送端和接收端用Topic進行關聯。這個Topic可以理解為我們這裡“倉庫”的地址,這樣就可以實現點對點和廣播兩種方式進行訊息的分發。

  • 生產消費者模型圖
    在這裡插入圖片描述
  • 一句話總結:解決程式解耦,較少的資源解決高併發的問題
import queue,threading,time
q=queue.Queue()

def product(arg):
    q.put(str(arg)+'包子')
def consumer(arg):
    print(arg,q.get())
for i in range(3):
    t=threading.Thread(target=product,args=(i,))
    t.start()
for j in range(3):
    t=threading.Thread(target=consumer,args=(j,))
    t.start()