PriorityBlockingQueue按权重排序需明确权重与优先级关系:权重越小优先级越高则用升序比较,越大越高则用降序;可通过实现Comparable接口或传入Comparator实现,且仅poll/take/peek保证顺序。

PriorityBlockingQueue 默认按元素自然顺序排序(即实现 Comparable 接口的 compareTo() 方法),或使用构造时传入的 Comparator。所谓“按权重排序”,本质就是把“权重”作为排序依据——你需要明确:权重是数值越大优先级越高,还是越小越高?然后在比较逻辑中体现。
定义带权重的元素类(推荐实现 Comparable)
让任务类自身携带权重字段,并参与比较:
public class Task implements Comparable<Task> {
private String name;
private int weight; // 权重值,假设:值越小,优先级越高(如 1 > 5)
public Task(String name, int weight) {
this.name = name;
this.weight = weight;
}
@Override
public int compareTo(Task other) {
return Integer.compare(this.weight, other.weight); // 升序:小权先出
// 若想“权重越大越优先”,改用:return Integer.compare(other.weight, this.weight);
}
@Override
public String toString() {
return "Task{" + "name='" + name + '\'' + ", weight=" + weight + '}';
}
}
然后直接使用:
PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<>();
queue.put(new Task("low", 10));
queue.put(new Task("high", 1));
queue.put(new Task("medium", 5));
System.out.println(queue.poll()); // 输出 Task{name='high', weight=1}
不修改元素类?用 Comparator 构造队列
如果无法修改元素类型(比如用的是第三方类),可在创建队列时传入自定义 Comparator:
立即学习“Java免费学习笔记(深入)”;
// 假设你有一个 PlainTask 类,没有实现 Comparable
class PlainTask {
String id;
int priority; // 权重字段名可能叫 priority / score / level 等
PlainTask(String id, int priority) {
this.id = id;
this.priority = priority;
}
}
PriorityBlockingQueue<PlainTask> queue = new PriorityBlockingQueue<>(
11, // 初始容量(可选)
(t1, t2) -> Integer.compare(t1.priority, t2.priority) // 小 priority 先执行
);
注意线程安全与排序稳定性
PriorityBlockingQueue 是线程安全的,但排序只在入队/出队时维护堆结构,不保证迭代顺序。也就是说:
-
queue.iterator()返回的顺序**不一定是优先级顺序**,不要依赖它遍历取高优任务; - 真正可靠的取数方式只有
poll()、take()、peek(); - 相同权重的元素之间**没有插入顺序保证**(不保证 FIFO),若需稳定,Comparator 中加入次级键(如时间戳、序列号)。
常见误区提醒
- 没重写
compareTo()或没传Comparator→ 抛ClassCastException(除非元素本身可比较); - 权重字段为
null→ 在比较中触发 NPE,建议在compareTo或Comparator中判空; - 误以为“阻塞”意味着会等待权重变化 → 不会。权重只在入队时快照一次,后续修改对象字段不影响队列内顺序。


















