介绍 Java PriorityBlockingQueue类

介绍 Java PriorityBlockingQueue类

本文我们聚焦PriorityBlockingQueue类,通过实例进行学习。假设我们已经了解Queue,首先演示PriorityBlockingQueue类中元素是根据优先级排序的,接着演示这种类型队列可用于阻塞线程,最后结合两个特性在多线程环境下处理数据。

元素优先级

与标准队列不同,不能增加任意类型元素,元素必须满足两个条件:

  1. 实现Comparable接口元素
  2. 不实现Comparable接口元素,提供Comparator比较器。

实现了Comparator 或Comparable的元素,PriorityBlockingQueue中的元素是排好序的。实现比较器的目的是让最高优先级的元素排在第一位,因此当从队列中删除元素时,总是删除最高优先级的元素。

为了方便理解,我们首先在单线程中使用,不使用多个线程可以很容易证明元素被排序了:

PriorityBlockingQueue<Integer> queue = new PriorityBlockingQueue<>();
ArrayList<Integer> polledElements = new ArrayList<>();
  
queue.add(1);
queue.add(5);
queue.add(2);
queue.add(3);
queue.add(4);
 
queue.drainTo(polledElements);
 
assertThat(polledElements).containsExactly(1, 2, 3, 4, 5);

我们看到,尽管元素被随机加入,但元素却按顺序出来。这时因为Integer实现了Comparable接口,这确保元素按照升序从队列中取出。

值得注意的是,当两个元素比较结果相同,不能保证两者的顺序。

优先队列阻塞功能

如果我们处理标准队列,使用poll方法获取元素,但如果队列为空,poll方法返回null。PriorityBlockingQueue 实现了BlockingQueue接口,增加了一些额外方法用于从空队列中删除元素时发生阻塞。我们通过示例演示take方法:

PriorityBlockingQueue<Integer> queue = new PriorityBlockingQueue<>();
 
new Thread(() -> {
  System.out.println("Polling...");
 
  try {
      Integer poll = queue.take();
      System.out.println("Polled: " + poll);
  } catch (InterruptedException e) {
      e.printStackTrace();
  }
}).start();
 
Thread.sleep(TimeUnit.SECONDS.toMillis(5));
System.out.println("Adding to queue");
queue.add(1);

虽然我们简单地使用sleep方法进行演示,输出结果为:

Polling...
Adding to queue
Polled: 1

证明了take方法被阻塞直到有新元素加入:

  1. 线程打印“Polling”证明线程启动
  2. 然后测试程序暂停大约5秒,证明take方法以及执行过了
  3. 我们给队列增加元素,几乎立刻看到“Polled:1”证明take方法返回元素

值得提及的是,BlockingQueue接口也提供了队列满时的阻塞方法。然而PriorityBlockingQueue 队列时无限制的,意味着永远不会满,总是可能增加新的元素。

演示同时使用阻塞和优先级两个特性

现在解释PriorityBlockingQueue队列的两个概念,通过示例同时使用两者进行说明。我们对前面示例进行简单修改,给队列中增加更多元素:

Thread thread = new Thread(() -> {
    System.out.println("Polling...");
    while (true) {
        try {
            Integer poll = queue.take();
            System.out.println("Polled: " + poll);
        } 
        catch (InterruptedException e) { 
            e.printStackTrace();
        }
    }
});
 
thread.start();
 
Thread.sleep(TimeUnit.SECONDS.toMillis(5));
System.out.println("Adding to queue");
 
queue.addAll(newArrayList(1, 5, 6, 1, 2, 6, 7));
Thread.sleep(TimeUnit.SECONDS.toMillis(1));

我们看到首先队列线程被阻塞并等待元素加入至队列。然后给队列增加一些元素,最后显示队列按照优先顺序处理元素。输出结果如下:

Polling...
Adding to queue
Polled: 1
Polled: 1
Polled: 2
Polled: 5
Polled: 6
Polled: 6
Polled: 7

总结

本文我们演示了PriorityBlockingQueue 队列的两大特性:按优先顺序进行处理,对空队列情况,获取方法会阻塞线程。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值