如何在Python中实现优先级队列?
阅读更多:Python 教程
介绍…
队列模块提供了适用于多线程编程的先进先出(FIFO)、后进先出(LIFO)数据结构。队列可用于安全地在创建者和使用者线程之间传递数据或任何广泛的信息,例如会话详细信息、路径、变量等。锁通常由调用者处理。
注意: 本讨论假定您已经理解队列的一般性质。如果您不理解,可能需要在继续之前阅读一些参考文献。
1. 让我们实现一个基本的FIFO队列。
import queue
fifo = queue.Queue()
# 将数字放入队列
for i in range(5):
fifo.put(i)
# 如果队列不为空,则从队列中获取数字
print(f"输出 \n")
while not fifo.empty():
print(f" {fifo.get()} ")
输出
0
1
2
3
4
2. 上面的示例使用单个线程,以展示如何按顺序从队列中移除元素。
3. 让我们实现一个基本的LIFO队列。
import queue
lifo = queue.LifoQueue()
# 将数字放入队列
for i in range(5):
lifo.put(i)
print(f"输出 \n")
# 如果队列不为空,则从队列中获取数字
while not lifo.empty():
print(f" {lifo.get()} ")
输出
4
3
2
1
0
4. 上面的示例显示,最后放入队列的元素通过get被移除。
5. 最后,我们将看到如何实现优先级队列。
有时候队列中项目的处理顺序需要基于它们的优先级,而不仅仅是它们被创建或添加到队列中的顺序。例如,在生产中运行的业务关键作业需要最高的CPU,并且比开发人员想要打印的某个作业具有优先权。PriorityQueue使用队列内容的排序顺序来决定要检索哪个项目。
import queue
import threading
# 获取优先级和描述并验证优先级的类
class Job:
def __init__(self, priority, description):
self.priority = priority
self.description = description
print('新任务:', description)
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
# 创建优先级队列并定义优先级
q = queue.PriorityQueue()
q.put(Job(90, '开发人员-打印作业'))
q.put(Job(2, '业务-报告作业'))
q.put(Job(1, '业务-关键作业'))
# 处理任务
def process_job(q):
while True:
next_job = q.get()
print(f" *** 现在,处理任务 - {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()
输出
新任务: 开发人员-打印作业
新任务: 业务-报告作业
新任务: 业务-关键作业
输出
*** 现在,处理任务 - 业务-关键作业
*** 现在,处理任务 - 业务-报告作业
*** 现在,处理任务 - 开发人员-打印作业
6. 本例中有多个线程消耗作业,根据队列中项目的优先级进行处理。处理顺序基于业务关键性,而不是它们被添加的顺序。