每週一個 Python 模組 | Queue

yongxinz發表於2018-12-14

專欄地址:每週一個 Python 模組

Queue 是 Python 標準庫中的執行緒安全的佇列(FIFO)實現,提供了一個適用於多執行緒程式設計的先進先出的資料結構,即佇列,用來在生產者和消費者執行緒之間的資訊傳遞。

有一點需要注意,Python2 中模組名是 Queue,而 Python3 是 queue。

基本 FIFO 佇列

class Queue.Queue(maxsize=0)

FIFO 即 First in First Out,先進先出。Queue 提供了一個基本的 FIFO 容器,使用方法很簡單,maxsize 是個整數,指明瞭佇列中能存放的資料個數的上限。一旦達到上限,插入會導致阻塞,直到佇列中的資料被消費掉。如果maxsize 小於或者等於 0,佇列大小沒有限制。

舉個栗子:

import Queue

q = Queue.Queue()

for i in range(5):
    q.put(i)

while not q.empty():
    print q.get()
    
# output
# 0
# 1
# 2
# 3
# 4
複製程式碼

LIFO 佇列

class Queue.LifoQueue(maxsize=0)

LIFO 即 Last in First Out,後進先出。與棧的類似,使用也很簡單,maxsize 用法同上。

再舉個栗子:

import Queue

q = Queue.LifoQueue()

for i in range(5):
    q.put(i)

while not q.empty():
    print q.get()
    
# output
# 4
# 3
# 2
# 1
# 0
複製程式碼

可以看到僅僅是將Queue.Quenu 類替換為Queue.LifoQueue 類。

優先順序佇列

class Queue.PriorityQueue(maxsize=0)

構造一個優先佇列。maxsize 用法同上。

import Queue
import threading

class Job(object):
    def __init__(self, priority, description):
        self.priority = priority
        self.description = description
        print 'Job:',description
        return
    def __cmp__(self, other):
        return cmp(self.priority, other.priority)

q = Queue.PriorityQueue()

q.put(Job(3, 'level 3 job'))
q.put(Job(10, 'level 10 job'))
q.put(Job(1, 'level 1 job'))

def process_job(q):
    while True:
        next_job = q.get()
        print 'for:', next_job.description
        q.task_done()

workers = [threading.Thread(target=process_job, args=(q,)),
        threading.Thread(target=process_job, args=(q,))
        ]

for w in workers:
    w.setDaemon(True)
    w.start()

q.join()

# output
# Job: level 3 job
# Job: level 10 job
# Job: level 1 job
# for: level 1 job
# for: level 3 job
# for: job: level 10 job
複製程式碼

一些常用方法

task_done()

意味著之前入隊的一個任務已經完成。由佇列的消費者執行緒呼叫。每一個 get() 呼叫得到一個任務,接下來的 task_done() 呼叫告訴佇列該任務已經處理完畢。

如果當前一個join()正在阻塞,它將在佇列中的所有任務都處理完時恢復執行(即每一個由put()呼叫入隊的任務都有一個對應的task_done()呼叫)。

join()

阻塞呼叫執行緒,直到佇列中的所有任務被處理掉。

只要有資料被加入佇列,未完成的任務數就會增加。當消費者執行緒呼叫task_done()(意味著有消費者取得任務並完成任務),未完成的任務數就會減少。當未完成的任務數降到 0,join() 解除阻塞。

put(item[, block[, timeout]])

item放入佇列中。

  1. 如果可選的引數blockTruetimeout為空物件(預設的情況,阻塞呼叫,無超時)。
  2. 如果timeout是個正整數,阻塞呼叫程式最多timeout秒,如果一直無空空間可用,丟擲Full異常(帶超時的阻塞呼叫)。
  3. 如果blockFalse,如果有空閒空間可用將資料放入佇列,否則立即丟擲Full異常。

其非阻塞版本為put_nowait等同於put(item, False)

get([block[, timeout]])

從佇列中移除並返回一個資料。blocktimeout引數同put方法。其非阻塞方法為get_nowait()相當與get(False)

empty()

如果佇列為空,返回True,反之返回False

相關文件:

pymotw.com/3/queue/ind…

www.cnblogs.com/itogo/p/563…

相關文章