PriorityBlockingQueue 是线程安全、无界、基于最小堆的优先级阻塞队列,put 不阻塞,take 空时阻塞;支持自然排序或自定义 Comparator,不允许 null,不保证同等优先级 FIFO,遍历无序。

PriorityBlockingQueue 是 Java 并发包(java.util.concurrent)中提供的一个线程安全、无界、支持优先级排序的阻塞队列。它底层基于可变数组的堆(最小堆),默认按自然顺序排序,也支持自定义 Comparator。由于它是无界的,put() 永远不会阻塞;而 take() 在队列为空时会阻塞,直到有元素入队。
如何创建带自定义优先级的 PriorityBlockingQueue
默认构造器使用元素的自然顺序(要求元素实现 Comparable),更常见的是传入 Comparator 来定义业务优先级逻辑:
- 例如,任务按执行时间越早越优先(升序):用
Comparator.comparingLong(task -> task.executeAt) - 或按重要等级降序(高优先级数字大):用
(a, b) -> Integer.compare(b.priority, a.priority) - 注意:Comparator 必须是线程安全的(通常为无状态 lambda 或静态比较器),不可依赖共享可变状态
典型使用场景:优先级任务调度器
适合构建“延迟/定时/紧急任务”混合调度系统,比如消息推送、告警处理、后台作业队列:
- 定义任务类,包含优先级字段(如
int priority、long scheduledTime)并实现Comparable,或单独提供Comparator - 生产者线程调用
queue.put(task)入队(不阻塞) - 消费者线程循环调用
queue.take()获取最高优先级任务(若空则阻塞等待) - 无需手动加锁,所有操作(
put/take/peek)天然线程安全
关键行为与注意事项
理解它的特性才能避免误用:
立即学习“Java免费学习笔记(深入)”;
-
无界性:内部数组会自动扩容,但极端情况下可能 OOM;如需容量控制,应自行封装或选用其他队列(如
DelayedQueue配合ScheduledThreadPoolExecutor) -
非完全实时排序:只保证
take()取出的是当前队列中优先级最高的元素,不保证遍历(iterator())有序,也不支持按优先级查找或删除任意元素 -
不允许 null 元素:插入
null会抛NullPointerException -
不保证同等优先级的 FIFO:相同优先级的元素取出顺序不确定(堆结构本身不维护插入次序);如需稳定顺序,可在
Comparator中加入插入时间戳作为第二排序条件
一个简洁可用的示例
定义一个按优先级 + 时间戳排序的任务:
class Task implements Comparable<Task> {final int priority;
final long timestamp = System.nanoTime();
Task(int priority) { this.priority = priority; }
public int compareTo(Task o) {
int cmp = Integer.compare(o.priority, this.priority); // 高优先级数字大 → 降序
return cmp != 0 ? cmp : Long.compare(this.timestamp, o.timestamp); // 同优先级按插入先后
}
}
然后:
PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<>();queue.put(new Task(5));
queue.put(new Task(1));
System.out.println(queue.take().priority); // 输出 5(最高优先级)


















