Python數(shù)據(jù)結(jié)構(gòu)與算法—優(yōu)先級(jí)隊(duì)列Queue
前言
queue庫(kù)提供了一個(gè)適用于多線程編程的先進(jìn)先出(FIFO)數(shù)據(jù)結(jié)構(gòu),可以用來(lái)在生產(chǎn)者與消費(fèi)者線程之間安全地傳遞消息或其他數(shù)據(jù)。
它會(huì)為調(diào)用者處理鎖定,使多個(gè)線程可以安全而更容易地處理同一個(gè)Queue實(shí)例。Queue的大小可能受限,以限制內(nèi)存使用或處理。
基本用法
Queue類實(shí)現(xiàn)了一個(gè)基本的先進(jìn)先出容器。使用put()將元素增加到這個(gè)序列的一端,使用get()從另一端刪除。具體代碼如下所示:
- import queue
- q = queue.Queue()
- for i in range(1, 10):
- q.put(i)
- while not q.empty():
- print(q.get(), end=" ")
運(yùn)行之后,效果如下:
這里我們依次添加1到10到隊(duì)列中,因?yàn)橄冗M(jìn)先出,所以出來(lái)的順序也與添加的順序相同。
LIFO隊(duì)列
既然有先進(jìn)先出隊(duì)列queue,那么數(shù)據(jù)結(jié)構(gòu)中肯定也有后進(jìn)先出的隊(duì)列。后進(jìn)先出的隊(duì)列為:LifoQueue,示例如下:
- import queue
- q = queue.LifoQueue()
- for i in range(1, 10):
- q.put(i)
- while not q.empty():
- print(q.get(), end=" ")
運(yùn)行之后,效果如下:
優(yōu)先隊(duì)列
在操作系統(tǒng)中,我們常常會(huì)根據(jù)優(yōu)先級(jí)來(lái)處理任務(wù),比如系統(tǒng)的優(yōu)先級(jí)最高,我們肯定優(yōu)先處理系統(tǒng)任務(wù),然后才處理用戶的任務(wù)。同樣,queue庫(kù)給我們提供了PriorityQueue來(lái)處理優(yōu)先級(jí)的隊(duì)列。
示例如下:
- import queue
- import threading
- class Job:
- def __init__(self, priority, desc):
- self.priority = priority
- self.desc = desc
- print("New Job:", desc)
- return
- def __eq__(self, other):
- try:
- return self.priority == other.priority
- except AttributeError:
- return NotImplemented
- def __lt__(self, other):
- try:
- return self.priority > other.priority
- except AttributeError:
- return NotImplemented
- def process_Job(q):
- while True:
- next_job = q.get()
- print(next_job.desc)
- q.task_done()
- q = queue.PriorityQueue()
- q.put(Job(5, "Five Job"))
- q.put(Job(15, "Fifteen Job"))
- q.put(Job(1, "One Job"))
- workers = [
- threading.Thread(target=process_Job, args=(q,)),
- threading.Thread(target=process_Job, args=(q,)),
- ]
- for work in workers:
- work.setDaemon(True)
- work.start()
- q.join()
運(yùn)行之后,效果如下:
這里,我們默認(rèn)數(shù)值越大優(yōu)先級(jí)越高,可以看到15先執(zhí)行,然后再是5,1任務(wù)。這個(gè)例子展現(xiàn)了有多個(gè)線程在處理任務(wù)時(shí),要根據(jù)get()時(shí)隊(duì)列中元素的優(yōu)先級(jí)來(lái)處理。