python3.6 queue模塊

python中的queue模塊其實(shí)是對(duì)數(shù)據(jù)結(jié)構(gòu)中隊(duì)列這種數(shù)據(jù)結(jié)構(gòu)的封裝,把抽象的數(shù)據(jù)結(jié)構(gòu)封裝成類的屬性和方法。這里主要談下,這些方法。

數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)

棧(stack)也可以說是種先行后出隊(duì)列(First in Last out),這種數(shù)據(jù)結(jié)構(gòu),是先進(jìn)后出的特點(diǎn)。

打個(gè)比方:比如我們把一本一本的書放進(jìn)一個(gè)剛好能容下的桶里面,后放入的書會(huì)壓著先放入的書。如果我們想要從桶里面取出書籍,那么就只有從后放入的書種先取出來。類似于這種先進(jìn)后出的模型便是了。

隊(duì)列(queue)特點(diǎn)是先進(jìn)先出(First in First out)。

打個(gè)比方:我們?nèi)ナ程门抨?duì)的時(shí)候,總是先去排隊(duì)的人能夠先打到飯,后進(jìn)入隊(duì)列排隊(duì)的人總是后打到飯。這樣的數(shù)據(jù)類型便成為隊(duì)列。

如果還想學(xué)習(xí)更多關(guān)于數(shù)據(jù)結(jié)構(gòu)的知識(shí),可以去買本書籍,推薦《大話數(shù)據(jù)結(jié)構(gòu)》,這本書很淺顯易懂的講解了數(shù)據(jù)結(jié)構(gòu)的知識(shí)。這本書一個(gè)大佬也推出了一個(gè)配套的教學(xué)視頻,《小甲魚數(shù)據(jù)結(jié)構(gòu)》(上bilibili.com就可以搜索到)。

queue模塊中表達(dá)隊(duì)列

在隊(duì)列中涉及到這樣的幾個(gè)操作:入隊(duì)(把數(shù)據(jù)添加到隊(duì)尾)、出隊(duì)(從隊(duì)首取出一個(gè)數(shù)據(jù))、隊(duì)列初始化(創(chuàng)建一個(gè)隊(duì)列)、銷毀一個(gè)隊(duì)列(把整個(gè)隊(duì)列的數(shù)據(jù)從內(nèi)存中刪除)、判斷隊(duì)列是否為空、判斷隊(duì)列是否滿、獲取隊(duì)列的長度。

python封裝好的隊(duì)列方法

import queue

q = queue.Queue(3)  # 調(diào)用構(gòu)造函數(shù),初始化一個(gè)大小為3的隊(duì)列
print(q.empty())  # 判斷隊(duì)列是否為空,也就是隊(duì)列中是否有數(shù)據(jù)
#  入隊(duì),在隊(duì)列尾增加數(shù)據(jù), block參數(shù),可以是True和False 意思是如果隊(duì)列已經(jīng)滿了則阻塞在這里,
# timeout 參數(shù) 是指超時(shí)時(shí)間,如果被阻塞了那最多阻塞的時(shí)間,如果時(shí)間超過了則報(bào)錯(cuò)。
q.put(13, block=True, timeout=5)
print(q.full())  # 判斷隊(duì)列是否滿了,這里我們隊(duì)列初始化的大小為3
print(q.qsize())  # 獲取隊(duì)列當(dāng)前數(shù)據(jù)的個(gè)數(shù)
#  block參數(shù)的功能是 如果這個(gè)隊(duì)列為空則阻塞,
#  timeout和上面一樣,如果阻塞超過了這個(gè)時(shí)間就報(bào)錯(cuò),如果想一只等待這就傳遞None
print(q.get(block=True, timeout=None))

#  queue模塊還提供了兩個(gè)二次封裝了的函數(shù),
q.put_nowait(23)  # 相當(dāng)于q.put(23, block=False)
q.get_nowait()  # 相當(dāng)于q.get(block=False)

此外,queue模塊實(shí)現(xiàn)了面向多生產(chǎn)線程、多消費(fèi)線程的隊(duì)列。

task_done()
意味著之前入隊(duì)的一個(gè)任務(wù)已經(jīng)完成。由隊(duì)列的消費(fèi)者線程調(diào)用。每一個(gè)get()調(diào)用得到一個(gè)任務(wù),接下來的task_done()調(diào)用告訴隊(duì)列該任務(wù)已經(jīng)處理完畢。

如果當(dāng)前一個(gè)join()正在阻塞,它將在隊(duì)列中的所有任務(wù)都處理完時(shí)恢復(fù)執(zhí)行(即每一個(gè)由put()調(diào)用入隊(duì)的任務(wù)都有一個(gè)對(duì)應(yīng)的task_done()調(diào)用)。

join()
阻塞調(diào)用線程,直到隊(duì)列中的所有任務(wù)被處理掉。

只要有數(shù)據(jù)被加入隊(duì)列,未完成的任務(wù)數(shù)就會(huì)增加。當(dāng)消費(fèi)者線程調(diào)用task_done()(意味著有消費(fèi)者取得任務(wù)并完成任務(wù)),未完成的任務(wù)數(shù)就會(huì)減少。當(dāng)未完成的任務(wù)數(shù)降到0,join()解除阻塞。

這兩個(gè)方法到底怎么用呢?下面我給出兩個(gè)例子:

import queue

q = queue.Queue(3)
q.put(13, block=True, timeout=5)
q.put_nowait(23)
q.task_done()
print(q.get())
q.join()

這段代碼執(zhí)行完后會(huì)一直阻塞著

import queue

q = queue.Queue(3)
q.put(13, block=True, timeout=5)
q.task_done()
q.put_nowait(23)
q.task_done()
print(q.get())
q.join()

這段代碼執(zhí)行后并不會(huì)會(huì)阻塞著,這是為什么呢?

其實(shí)為了實(shí)現(xiàn)多線程環(huán)境下對(duì)隊(duì)列的支持,當(dāng)我們調(diào)用put的時(shí)候可以看做我們給這個(gè)隊(duì)列增加了一個(gè)任務(wù),只有到調(diào)用task_done()函數(shù)是才表示完成了一個(gè)任務(wù)。而join()函數(shù)表示我們所有的任務(wù)都完成后才會(huì)不被阻塞。

python封裝好的棧方法

棧的方法和隊(duì)列的一模一樣,只是有一點(diǎn)不同,我們在調(diào)用,put()get()的順序是不一樣的。其他的東西都是和上面隊(duì)列是一樣的。

python封裝好的優(yōu)先隊(duì)列方法

什么是優(yōu)先隊(duì)列
普通的隊(duì)列其實(shí)是:先進(jìn)后出,或者是先進(jìn)先出。
但是優(yōu)先隊(duì)列就不一樣了,它是怎么出的規(guī)則不和進(jìn)入的順序有關(guān),是和他的優(yōu)先級(jí)有關(guān),當(dāng)入隊(duì)的時(shí)候我們就會(huì)根據(jù)這個(gè)數(shù)據(jù)的優(yōu)先級(jí)進(jìn)行排序,優(yōu)先級(jí)高的就排在前面,然后出隊(duì)的時(shí)候就是先出隊(duì)。

看這樣一個(gè)例子:

import queue

q = queue.PriorityQueue(4)
q.put((1,'abcb'))
q.put((1,'abc1'))
q.put((1,'abc3'))
q.put((2,'abc4'))

print(q.get())
print(q.get())
print(q.get())
print(q.get())

這里會(huì)根據(jù)數(shù)據(jù)的大小比較進(jìn)行排序,然后在調(diào)用get()時(shí)根據(jù)優(yōu)先順序進(jìn)行出隊(duì)列。

python封裝好的雙向隊(duì)列方法

可以把雙向隊(duì)列看做是隊(duì)列和棧的一個(gè)升級(jí)版。
棧是在一端進(jìn)行入棧和出站,而隊(duì)列是在一端入棧一端出棧。
而雙向隊(duì)列則是兩端都可以進(jìn)同時(shí)也可以出。

import queue

q = queue.deque(3)  # 初始化一個(gè)雙向隊(duì)列
q.append(12)  # 右邊進(jìn)
q.pop()  # 右邊出

q.appendleft(34)  # 左邊進(jìn)
q.popleft()  # 左邊出

python自己有提供的內(nèi)存回收機(jī)制,所以不需要我們手動(dòng)銷毀隊(duì)列或者棧

推薦一些好文章

簡析Python中的四種隊(duì)列
每周一個(gè) Python 模塊 | Queue
Python Queue 源碼解讀
Python 多線程|Queue隊(duì)列|生產(chǎn)者消費(fèi)者模式|

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,662評(píng)論 1 32
  • 必備的理論基礎(chǔ) 1.操作系統(tǒng)作用: 隱藏丑陋復(fù)雜的硬件接口,提供良好的抽象接口。 管理調(diào)度進(jìn)程,并將多個(gè)進(jìn)程對(duì)硬件...
    drfung閱讀 3,762評(píng)論 0 5
  • iOS多線程編程 基本知識(shí) 1. 進(jìn)程(process) 進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序,就是一段程序的執(zhí)...
    陵無山閱讀 6,345評(píng)論 1 14
  • 從哪說起呢? 單純講多線程編程真的不知道從哪下嘴。。 不如我直接引用一個(gè)最簡單的問題,以這個(gè)作為切入點(diǎn)好了 在ma...
    Mr_Baymax閱讀 2,911評(píng)論 1 17
  • 2018.2.8 唐春桃 忙碌的一天從清晨開始,今天早上開始對(duì)家里大清潔,現(xiàn)在剛做完,整整用了一天的時(shí)間,家里煥然...
    tangchuntao唐糖閱讀 120評(píng)論 5 8

友情鏈接更多精彩內(nèi)容