久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Python collections.deque雙邊隊(duì)列原理詳解

瀏覽:2日期:2022-07-09 09:49:19

隊(duì)列是一種只允許在一端進(jìn)行插入操作,而在另一端進(jìn)行刪除操作的線(xiàn)性表。

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

collections.deque

deque是雙端隊(duì)列(double-ended queue)的縮寫(xiě),由于兩端都能編輯,deque既可以用來(lái)實(shí)現(xiàn)棧(stack)也可以用來(lái)實(shí)現(xiàn)隊(duì)列(queue)。

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

Python collections.deque雙邊隊(duì)列原理詳解

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

deque也支持in操作符,可以使用如下寫(xiě)法:

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

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

# 順時(shí)針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]

# 逆時(shí)針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]

線(xiàn)程安全方面,通過(guò)查看collections.deque中的append()、pop()等方法的源碼可以知道,他們都是原子操作,所以是GIL保護(hù)下的線(xiàn)程安全方法。

static PyObject *deque_append(dequeobject *deque, PyObject *item) { Py_INCREF(item);if (deque_append_internal(deque, item, deque->maxlen) < 0) return NULL;Py_RETURN_NONE;}

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

Python collections.deque雙邊隊(duì)列原理詳解

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

queue.Queue & asyncio.Queue

queue.Queue和asyncio.Queue都是支持多生產(chǎn)者、多消費(fèi)者的隊(duì)列,基于collections.deque,他們都提供了Queue(FIFO隊(duì)列)、PriorityQueue(優(yōu)先級(jí)隊(duì)列)、LifoQueue(LIFO隊(duì)列),接口方面也相同。

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

queue.Queue asyncio.Queue 介紹 同步隊(duì)列 asyncio隊(duì)列 線(xiàn)程安全 是 否 超時(shí)機(jī)制 通過(guò)timeout參數(shù)實(shí)現(xiàn) 通過(guò)asyncio.wait_for()方法實(shí)現(xiàn) qsize() 預(yù)估的隊(duì)列長(zhǎng)度(獲取qsize到下一個(gè)操作之間,queue有可能被其它的線(xiàn)程修改,導(dǎo)致qsize大小發(fā)生變化) 準(zhǔn)確的隊(duì)列長(zhǎng)度(由于是單線(xiàn)程,所以queue不會(huì)被其它線(xiàn)程修改) put() / set() put(item, block=True, timeout=None),可以通過(guò)設(shè)置block是否為T(mén)rue來(lái)配置put和set方法是否為阻塞,并且可以為阻塞操作設(shè)置最大時(shí)長(zhǎng)timeout,block為False時(shí)行為和put_nowait()方法一致。 put()方法會(huì)返回一個(gè)協(xié)程對(duì)象,所以沒(méi)有block參數(shù)和timeout參數(shù),如果需要非阻塞方法,可以使用put_nowait(),如果需要對(duì)阻塞方法應(yīng)用超時(shí),可以使用coroutine asyncio.wait_for()。

multiprocessing.Queue

multiprocessing提供了三種隊(duì)列,分別是Queue、SimpleQueue、JoinableQueue。

Python collections.deque雙邊隊(duì)列原理詳解

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

multiprocessing.Queue底層是基于Pipe構(gòu)建的,但是數(shù)據(jù)傳遞時(shí)并不是直接寫(xiě)入Pipe,而是寫(xiě)入進(jìn)程本地buffer,通過(guò)一個(gè)feeder線(xiàn)程寫(xiě)入底層Pipe,這樣做是為了實(shí)現(xiàn)超時(shí)控制和非阻塞put/get,所以Queue提供了join_thread、cancel_join_thread、close函數(shù)來(lái)控制feeder的行為,close函數(shù)用來(lái)關(guān)閉feeder線(xiàn)程、join_thread用來(lái)join feeder線(xiàn)程,cancel_join_thread用來(lái)在控制在進(jìn)程退出時(shí),不自動(dòng)join feeder線(xiàn)程,使用cancel_join_thread有可能導(dǎo)致部分?jǐn)?shù)據(jù)沒(méi)有被feeder寫(xiě)入Pipe而導(dǎo)致的數(shù)據(jù)丟失。

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

SimpleQueue是一個(gè)簡(jiǎn)化的隊(duì)列,去掉了Queue中的buffer,沒(méi)有了使用Queue可能出現(xiàn)的問(wèn)題,但是put和get方法都是阻塞的并且沒(méi)有超時(shí)控制。

總結(jié)

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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 伊金霍洛旗| 定边县| 梓潼县| 开封县| 仁寿县| 来安县| 余姚市| 青阳县| 鄂托克前旗| 天水市| 肥城市| 洪洞县| 宜春市| 永胜县| 德保县| 威远县| 沾化县| 鸡东县| 农安县| 梨树县| 桐城市| 长沙市| 普陀区| 长春市| 桂阳县| 阜城县| 靖边县| 宁蒗| 桐庐县| 朝阳区| 册亨县| 林甸县| 禹州市| 临湘市| 建平县| 深圳市| 墨脱县| 潜江市| 冀州市| 锦屏县| 巫山县|