queue.PriorityQueue是带锁的线程安全队列,适用于多线程生产者-消费者场景;单线程排序取最小值时应直接用heapq,避免锁开销和内存浪费。

用 queue.PriorityQueue 做任务调度,别当普通列表用
它不是线程安全的“高性能堆”,而是带锁的队列,适合多线程生产者-消费者场景。如果你只是单线程排序取最小值,queue.PriorityQueue 反而拖慢速度、多占内存。
- 每次
put()和get()都触发锁操作和线程唤醒开销 - 内部用
heapq实现,但额外包了一层_queueC 模块 + 锁逻辑 - 元素必须可比较;如果存的是自定义对象,得实现
__lt__,否则抛TypeError: ' - 不能直接遍历或查看堆顶以外的元素——没有
peek(),也没法索引访问
heapq 才是 Python 里真正该手写的“优先队列”
90% 的本地优先级处理(比如 Dijkstra、Top-K、合并有序流)都应该用 heapq:零额外开销、原地建堆、支持所有常见操作。
-
heapq.heappush(heap, item)和heapq.heappop(heap)是核心,堆顶始终是heap[0] - 初始化用
heapq.heapify(list),比一个个heappush快得多(O(n) vs O(n log n)) - 要支持“延迟删除”或“更新优先级”?得自己维护一个
entry_finder字典 + 使用REMOVED标记,不然没法删中间节点 - 注意:Python 的
heapq只是最小堆;模拟最大堆就存(-priority, item)
自定义对象进堆时,__lt__ 写错就静默失败
错误不是立刻报,而是堆结构被破坏后某次 heappop 返回错值,或者排序结果乱序——因为 heapq 完全依赖 比较。
- 只实现
__lt__就够了,不用写__le__或__eq__;但必须保证逻辑自洽(比如 a - 避免在
__lt__里读外部状态或调用耗时函数,堆操作频繁,性能敏感 - 如果优先级相同还想保插入顺序,加个递增计数器字段,比如
(priority, counter, item),否则相同优先级的元素可能乱序
别把 queue.PriorityQueue 和 heapq 混着用
它们底层都靠 heapq,但接口语义完全不同:一个是并发队列,一个是数据结构工具。混用等于给自己埋竞态和类型错误。
立即学习“Python免费学习笔记(深入)”;
- 不要试图从
queue.PriorityQueue里取.queue属性去手动heapq.heappop——那个 list 不是随时可安全操作的堆结构 - 不要把
heapq建好的堆传给queue.PriorityQueue构造函数——它不认,会重新put所有元素,锁也白加 - 跨线程共享数据?用
queue.PriorityQueue;单线程算法逻辑?死磕heapq;边界模糊时,先问自己:有没有其他线程在同时put或get?
__lt__,它就不知道该排哪儿。**


















