2026/4/6 8:27:03
网站建设
项目流程
专业的外贸网站建设公司,百度网站下载,企业宣传图片模板,北京全网营销推广PriorityBlockingQueueE 是 Java 并发包#xff08;java.util.concurrent#xff09;中提供的一个线程安全的、无界、优先级队列。它的核心思想是#xff1a;每次取出的元素#xff0c;都是当前队列中“优先级最高”的那个元素#xff08;即最小值#xff0c;依据…PriorityBlockingQueueE是 Java 并发包java.util.concurrent中提供的一个线程安全的、无界、优先级队列。它的核心思想是每次取出的元素都是当前队列中“优先级最高”的那个元素即最小值依据自然排序或自定义比较器。一、关键特性总结特性说明线程安全所有公共操作都通过ReentrantLock加锁支持多线程并发访问。无界逻辑上理论上可以无限添加元素但受 JVM 内存限制可能抛OutOfMemoryError。不允许 null 元素插入null会抛NullPointerException。基于堆Heap实现底层使用数组表示的二叉堆最小堆保证queue[0]是优先级最高的元素。阻塞式取操作提供take()、poll(timeout)等方法在队列为空时可阻塞等待。不保证迭代顺序iterator()不按优先级顺序遍历如需有序必须用Arrays.sort(toArray())。插入/删除时间复杂度O(log n)因为要维护堆结构。二、核心机制解析1.底层数据结构二叉最小堆使用Object[] queue存储元素。对于任意节点i左孩子2*i 1右孩子2*i 2父节点(i - 1) / 2堆性质父节点 ≤ 子节点→ 根节点queue[0]是最小值最高优先级。2.扩容机制tryGrow当数组满时自动扩容小容量64增长较快 oldCap 2大容量增长 50%oldCap 1特殊设计扩容时不持有主锁lock而是用CAS 自旋锁allocationSpinLock避免阻塞消费者。目的防止生产者扩容时长时间持有锁导致消费者“饿死”。3.堆调整操作siftUp插入新元素后从底部向上调整冒泡到合适位置。siftDown删除根节点后把最后一个元素放到根再向下调整。分为两种版本siftUpComparable/siftDownComparable使用元素自身的compareTo()siftUpUsingComparator/siftDownUsingComparator使用外部Comparator4.构造函数逻辑如果传入的是SortedSet或PriorityQueue直接复用其排序规则无需重新建堆。否则对传入集合调用heapify()从底向上建堆时间复杂度 O(n)。5.阻塞与非阻塞操作方法行为offer(e)立即插入返回true永不阻塞因无界put(e)同offer语义上“可能阻塞”但实际不会take()队列空时阻塞直到有元素poll()队列空时立即返回 nullpoll(timeout, unit)队列空时最多等待 timeout 时间6.关于迭代器重要IteratorEitpq.iterator();// ❌ 不保证按优先级顺序遍历原因堆的数组存储不是排序数组只是满足堆性质。正确做法如需有序遍历必须Object[]arrpq.toArray();Arrays.sort(arr);// 或使用 Comparator三、FIFOEntry 示例解决“优先级相同时的公平性”当多个元素优先级相同compareTo 0默认不保证谁先出队。解决方案引入“插入顺序”作为第二排序键。classFIFOEntryEextendsComparable?superEimplementsComparableFIFOEntryE{staticfinalAtomicLongseqnewAtomicLong(0);finallongseqNum;// 插入序号finalEentry;publicintcompareTo(FIFOEntryEother){intresentry.compareTo(other.entry);if(res0)resLong.compare(seqNum,other.seqNum);// 先插入的先出returnres;}}使用时pq.offer(new FIFOEntry(myElement));四、典型使用场景任务调度系统高优先级任务先执行。事件处理紧急事件优先处理。合并多个有序流如多路归并配合take()阻塞特性。五、注意事项不要依赖iterator()的顺序避免在比较器中抛异常会导致队列状态不一致。内存风险虽然是“无界”但大量积压会导致 OOM。性能高并发下所有操作串行化单锁吞吐量不如ConcurrentLinkedQueue但语义不同。总结PriorityBlockingQueue线程安全的 PriorityQueue BlockingQueue 接口它适合需要按优先级消费、且允许多线程协作的场景但要注意其无界性和迭代无序性。如果你理解了二叉堆、CAS 自旋锁、以及阻塞条件Condition notEmpty就掌握了它的精髓。