PriorityBlockingQueue 是线程安全的无界优先队列,基于堆实现,支持自然排序或自定义 Comparator,put/take 操作自动同步;高优先级数字需用 reversed() 反转比较逻辑;不保证同优先级顺序,也不支持动态改优先级。

PriorityBlockingQueue 是 Java 并发包中一个线程安全的无界优先队列,适合用于实现带优先级的任务调度。它底层基于堆结构,支持按自然顺序或自定义比较器排序,且所有操作(如 put、take)都是线程安全的,无需额外加锁。
定义可比较的任务类
要让任务按优先级执行,任务对象必须能被比较。通常有两种方式:
- 让任务类实现
Comparable接口,重写compareTo()方法(例如按 priority 字段升序或降序) - 创建
PriorityBlockingQueue时传入Comparator,更灵活,避免修改任务类
注意:优先级数值越小默认越先出队(最小堆),若希望高优先级数字(如 10 > 1)先执行,需在比较逻辑中反转顺序。
构造并初始化队列
推荐显式指定比较器,避免依赖自然排序带来的歧义:
立即学习“Java免费学习笔记(深入)”;
PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<>(
11, // 初始容量(仅提示,实际自动扩容)
Comparator.comparingInt(Task::getPriority).reversed() // 高优先级数字先执行
);
不传比较器时,要求 Task 实现 Comparable;传了比较器则忽略 Comparable。
生产者:提交带优先级的任务
多个线程可通过 put() 安全入队,该方法不会阻塞(因队列为无界):
-
queue.put(new Task("send-alert", 10));// 高优先级告警 -
queue.put(new Task("log-info", 1));// 低优先级日志
任务插入后,队列内部自动调整堆结构,保证下次 take() 返回当前最高优先级任务。
消费者:阻塞获取并执行任务
典型工作线程循环调用 take() —— 若队列为空则阻塞,有任务时立即返回最高优先级项:
while (!Thread.currentThread().isInterrupted()) {
try {
Task task = queue.take(); // 阻塞直到有任务
task.execute();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
多个消费者线程共用同一个 PriorityBlockingQueue 是安全的,take() 和 put() 内部已同步。
不复杂但容易忽略:PriorityBlockingQueue 不保证相同优先级任务的执行顺序(非公平),也不支持动态修改已入队任务的优先级——改字段无效,需重新入队。如需严格 FIFO + 优先级,可考虑组合使用 PriorityQueue + 显式锁,或选用 DelayQueue 等替代方案。



















