python五種隊列詳解

隊列的類別

threading.Queue
multiprocessing.Queue
queue.Queue
asyncio.Queue
List方式實現(xiàn)
隊列是一種只允許在一端進行插入操作彤灶,而在另一端進行刪除操作的線性表回溺。

在Python文檔中搜索隊列(queue)會發(fā)現(xiàn)艰赞,Python標(biāo)準(zhǔn)庫中包含了四種隊列,分別是queue.Queue / asyncio.Queue / multiprocessing.Queue / collections.deque描滔。

01

collections.deque

deque是雙端隊列(double-ended queue)的縮寫颗管,由于兩端都能編輯迄埃,deque既可以用來實現(xiàn)棧(stack)也可以用來實現(xiàn)隊列(queue)胎许。

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

image

相比于list實現(xiàn)的隊列栏妖,deque實現(xiàn)擁有更低的時間和空間復(fù)雜度乱豆。list實現(xiàn)在出隊(pop)和插入(insert)時的空間復(fù)雜度大約為O(n),deque在出隊(pop)和入隊(append)時的時間復(fù)雜度是O(1)吊趾。

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

1q = collections.deque([1, 2, 3, 4])2print(5 in q)  # False3print(1 in q)  # True

deque還封裝了順逆時針的旋轉(zhuǎn)的方法:rotate。

 1# 順時針 2q = collections.deque([1, 2, 3, 4]) 3q.rotate(1) 4print(q)  # [4, 1, 2, 3] 5q.rotate(1) 6print(q)  # [3, 4, 1, 2] 7 8# 逆時針 9q = collections.deque([1, 2, 3, 4])10q.rotate(-1)11print(q)  # [2, 3, 4, 1]12q.rotate(-1)13print(q)  # [3, 4, 1, 2]

線程安全方面论泛,通過查看collections.deque中的append()揩尸、pop()等方法的源碼可以知道,他們都是原子操作屁奏,所以是GIL保護下的線程安全方法岩榆。

1static PyObject *2deque_append(dequeobject *deque, PyObject *item) { 3    Py_INCREF(item);4    if (deque_append_internal(deque, item, deque->maxlen) < 0) 5        return NULL;6    Py_RETURN_NONE;7}

通過dis方法可以看到,append是原子操作(一行字節(jié)碼)。

image

綜上勇边,collections.deque是一個可以方便實現(xiàn)隊列的數(shù)據(jù)結(jié)構(gòu)犹撒,具有線程安全的特性,并且有很高的性能粒褒。

02

queue.Queue & asyncio.Queue

queue.Queue和asyncio.Queue都是支持多生產(chǎn)者识颊、多消費者的隊列,基于collections.deque奕坟,他們都提供了Queue(FIFO隊列)祥款、PriorityQueue(優(yōu)先級隊列)、LifoQueue(LIFO隊列)月杉,接口方面也相同刃跛。

區(qū)別在于queue.Queue適用于多線程的場景,asyncio.Queue適用于協(xié)程場景下的通信苛萎,由于asyncio的加成桨昙,queue.Queue下的阻塞接口在asyncio.Queue中則是以返回協(xié)程對象的方式執(zhí)行,具體差異如下表:

image

03

multiprocessing.Queue

multiprocessing提供了三種隊列首懈,分別是Queue绊率、SimpleQueue谨敛、JoinableQueue究履。

image

multiprocessing.Queue既是線程安全也是進程安全的,相當(dāng)于queue.Queue的多進程克隆版脸狸。和threading.Queue很像最仑,multiprocessing.Queue支持put和get操作,底層結(jié)構(gòu)是multiprocessing.Pipe炊甲。

multiprocessing.Queue底層是基于Pipe構(gòu)建的泥彤,但是數(shù)據(jù)傳遞時并不是直接寫入Pipe,而是寫入進程本地buffer卿啡,通過一個feeder線程寫入底層Pipe吟吝,這樣做是為了實現(xiàn)超時控制和非阻塞put/get,所以Queue提供了join_thread颈娜、cancel_join_thread剑逃、close函數(shù)來控制feeder的行為,close函數(shù)用來關(guān)閉feeder線程官辽、join_thread用來join feeder線程蛹磺,cancel_join_thread用來在控制在進程退出時,不自動join feeder線程同仆,使用cancel_join_thread有可能導(dǎo)致部分?jǐn)?shù)據(jù)沒有被feeder寫入Pipe而導(dǎo)致的數(shù)據(jù)丟失萤捆。

和threading.Queue不同的是,multiprocessing.Queue默認(rèn)不支持join()和task_done操作,這兩個支持需要使用mp.JoinableQueue對象俗或。

SimpleQueue是一個簡化的隊列市怎,去掉了Queue中的buffer,沒有了使用Queue可能出現(xiàn)的問題辛慰,但是put和get方法都是阻塞的并且沒有超時控制焰轻。

04

總結(jié)

通過對比可以發(fā)現(xiàn),上述四種結(jié)構(gòu)都實現(xiàn)了隊列昆雀,但是用處卻各有偏重辱志,collections.deque在數(shù)據(jù)結(jié)構(gòu)層面實現(xiàn)了隊列,但是并沒有應(yīng)用場景方面的支持,可以看做是一個基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)韭脊。queue模塊實現(xiàn)了面向多生產(chǎn)線程佳窑、多消費線程的隊列,asyncio.queue模塊則實現(xiàn)了面向多生產(chǎn)協(xié)程已球、多消費協(xié)程的隊列,而multiprocessing.queue模塊實現(xiàn)了面向多成產(chǎn)進程辅愿、多消費進程的隊列智亮。

05

參考

https://docs.python.org/3/library/collections.html#collections.deque
https://docs.python.org/3/library/queue.html
https://docs.python.org/3/library/asyncio-queue.html
https://docs.python.org/3/library/multiprocessing.html#multiprocessing.Queue
https://bugs.python.org/issue15329
http://blog.ftofficer.com/2009/12/python-multiprocessing-3-about-queue/
http://cyrusin.github.io/2016/04/27/python-gil-implementaion/

轉(zhuǎn)自:
https://mp.weixin.qq.com/s?__biz=MzU2NDQ3Mzg1NQ==&mid=2247483735&idx=1&sn=93fa50be8520f00204731ffc4038ec84&chksm=fc4b3bc7cb3cb2d12d5f251382bda4d4c511006bfdd007f7da43e2127e8e31449018b6c9c9ae&scene=0&key=d31433989bf9be8ae08a8739962021c539d8e589425405d9bdd38efb06b6adb5673b8eb767283507b8172d27bb16dbd349e759da50d394ecc293b16f0c56a37f5447841795644e782edee5d4262d6755&ascene=0&uin=MjUxNTEzODQxMg%3D%3D&devicetype=iMac+MacBookPro11%2C1+OSX+OSX+10.10.5+build(14F2511)&version=12020810&nettype=WIFI&lang=en&fontScale=100&pass_ticket=pBo%2BsLwQzk0m5MMoj%2F%2Be3mBnw1gcoaCOgLY8bZkzAF33btPbwHNOlNPinLY4kuNs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市点待,隨后出現(xiàn)的幾起案子阔蛉,更是在濱河造成了極大的恐慌,老刑警劉巖癞埠,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件状原,死亡現(xiàn)場離奇詭異,居然都是意外死亡苗踪,警方通過查閱死者的電腦和手機颠区,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來通铲,“玉大人毕莱,你說我怎么就攤上這事÷幔” “怎么了朋截?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碗啄。 經(jīng)常有香客問我质和,道長,這世上最難降的妖魔是什么稚字? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任饲宿,我火速辦了婚禮厦酬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘫想。我一直安慰自己仗阅,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布国夜。 她就那樣靜靜地躺著减噪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪车吹。 梳的紋絲不亂的頭發(fā)上筹裕,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音窄驹,去河邊找鬼朝卒。 笑死,一個胖子當(dāng)著我的面吹牛乐埠,可吹牛的內(nèi)容都是我干的抗斤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼丈咐,長吁一口氣:“原來是場噩夢啊……” “哼瑞眼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起棵逊,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤伤疙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后歹河,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掩浙,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡花吟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年秸歧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衅澈。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡键菱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出今布,到底是詐尸還是另有隱情经备,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布部默,位于F島的核電站侵蒙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏傅蹂。R本人自食惡果不足惜纷闺,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一算凿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧犁功,春花似錦氓轰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至限嫌,卻和暖如春靴庆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怒医。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工撒穷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人裆熙。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓端礼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親入录。 傳聞我的和親對象是個殘疾皇子蛤奥,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容