詳解Python中的四種佇列

2022-10-04 19:39:32 字數 2490 閱讀 5339

佇列是一種只允許在一端進行插入操作,而在另一端進行刪除操作的線性表。

在python文件中搜尋佇列(queue)會發現,python標準庫中包含了四種佇列,分別是queue.queue / asyncio.queue / multiprocessing.queue / collections.deque。

collections.deque

deque是雙端佇列(double-ended queue)的縮寫,由於兩端都能編輯,deque既可以用來實現棧(stack)也可以用來實現佇列(queue)。

deque支援豐富的操作方法,主要方法如圖:

相比於list實現的佇列,deque實現擁有更低的時間和空間複雜度。list實現在出隊(pop)和插入(insert)時的空間複雜度大約為o(n),deque在出隊(pop)和入隊(append)時的時間複雜度是o(1)。

deque也支援in操作符,可以使用如下寫法:

q = collections.deque([1, 2, 3, 4])

print(5 in q) # false

print(1 in q) # true

deq還封裝了順逆時針的旋轉的方法:rotate。

# 順時針

q = collections.deque([1, 2, 3, 4])

q.rotate(1)

print(q) # [4, 1, 2, 3]

q.rotate(1)

print(q) # [3, 4, 1, 2]

# 逆時針

q = collections.deque([1, 2, 3, 4])

q.rotate(-1)

print(q) # [2, 3, 4, 1]

q.rotate(-1)

print(q) # [3, 4, 1, 2]

執行緒安全方面,collections.deque中的append()、程式設計客棧pop()等方法都是原子操作,所以是gil保護下的執行緒安全方法。

static pyobject *

deque_append(dequeobject *deque, pyobject *item)

通過dis方法可以看到,append是原子操作(一行位元組碼sjqah)。

綜上,collections.deque是乙個可以方便實現佇列的資料結構,具有執行緒安全的特性,並且有很高的效能。

queue.queue & asyncio.queue

queue.queue和asyncio.queue都是支援多生產者、多消費者的佇列,基於collections.deque,他們都提供了queue(fifo佇列)、priorityqueue(優先順序佇列)、lifoqueue(lifo佇列),介面方面也相同。

區別在於queue.queue適用於多執行緒的場景,asyncio.queue適用於協程場景下的通訊,由於asyncio的加成,queue.程式設計客棧queue下的阻塞介面在asyncio.queue中則是以返回協程物件的方式執行,具體差異如下表:

multiprocessing.queue

multiprocessing提供了三種佇列,分別是queue、******queue、joinablequeue。

multiprocessing.queue既是執行緒安全也是程序安全的,相當於queue.queue的多程序轉殖版。和threading.queue很像,multiprocessing.queue支援put和get操作,底層結構是multiprocessing.pipe。

multiprocessing.queue底層是基於pipe構建的,但是資料傳遞時並不是直接寫入pipe,而是寫入程序本地buffer,通過乙個feeder執行緒寫入底層pipe,這樣做是為了實現超時控制和非阻塞put/get,所以queue提供了join_thread、cancel_join_thread、close函式來控制feeder的行為,close函式用來關閉feeder執行緒、join_thread用來join feeder執行緒,cancel_join_thread用來在控制在程序退出時,不自動join feeder執行緒,使用cancel_join_thread有可能導致部分資料沒有被feeder寫入pipe而導致的資料丟失。

和threading.queue不同的是,multiprocessing.queue預設不支援join()和task_done操作,這兩個支援需要使用mp.joinablequeue物件。

******queue是乙個簡化的佇列,去掉了queue中的buffer,沒有了使用queue可能出現的問題,但是put和get方法都是阻塞的並且沒有超時控制。

總結通過對比可以發現,上述四種結構都實現了佇列,但是用處卻各有偏重,coll程式設計客棧ections.deque在資料結構層面實現了佇列,但是並沒有應用場景方面的支援,可以看做是乙個基礎的資料結構。queue模組實現了面向多生產線程、多消費執行緒的佇列,asyncio.queue模組則實現了面向多生產協程、多消費協程的佇列,而multiprocessing.queue模組實現了面向多成產程序、多消費程序的佇列。

本文標題: 詳解python中的四種佇列

本文位址:

Python中內建的四種佇列

from queue import queue lilo佇列 q queue 建立佇列物件 q.put 0 在佇列尾部插入元素 q.put 1 q.put 2 print lilo佇列 q.queue 檢視佇列中的所有元素 print q.get 返回並刪除佇列頭部元素 print q.queue ...

python中四種命名方式

1 object 公用方法 2 object 半保護 被看作是 protect 意思是只有類物件和子類物件自己能訪問到這些變數,在模組或類外不可以使用,不能用 from module import 匯入。object 是為了避免與子類的方法名稱衝突,對於該識別符號描述的方法,父 類的方法不能輕易地被...

jsp四種屬性詳解

四種屬性範圍 1 page pagecontext 在乙個頁面中儲存屬性,跳轉之後無效 則乙個 page 範圍中的內容只能儲存在乙個頁面中 2 request 只在一次請求中儲存,伺服器跳轉後依然有效。request 屬性範圍表示的是在伺服器跳轉之後,所有設定的內容依然會儲存下來 頁面跳轉之後,可以...