Java中的PriorityBlockingQueue

时间:2020-01-09 10:35:11  来源:igfitidea点击:

Java中的PriorityBlockingQueue是BlockingQueue接口的实现,并且是java.util.concurrent包的一部分。

PriorityBlockingQueue是一个无边界队列

PriorityBlockingQueue在逻辑上是无界的,这与ArrayBlockingQueue(有界队列)和LinkedBlockingQueue(有界)可选。

尽管PriorityBlockingQueue是无限制的,但其初始容量可以指定,如果未指定,则默认为11. 此初始容量控制用于在队列上存储元素的数组的大小。

请注意,尽管队列在逻辑上是不受限制的,但是尝试尝试添加可能会由于资源耗尽而失败(导致OutOfMemoryError)。

Java PriorityBlockingQueue构造函数

  • PriorityBlockingQueue()创建一个具有默认初始容量(11)的PriorityBlockingQueue,该默认容量根据其自然顺序对元素进行排序。
  • PriorityBlockingQueue(int initialCapacity)创建一个具有指定初始容量的PriorityBlockingQueue,该容量根据其自然顺序对元素进行排序。
  • PriorityBlockingQueue(int initialCapacity,Comparator <?super E>比较器)创建一个具有指定初始容量的PriorityBlockingQueue,该容量根据指定的Comparator对其元素进行排序。
  • PriorityBlockingQueue(Collection <?extended E> c)创建一个PriorityBlockingQueue,其中包含指定集合中的元素。

PriorityBlockingQueue是线程安全的

Java中的PriorityBlockingQueue是java.util.PriorityQueue类的线程安全变体,并提供阻塞检索操作。插入方法永远不会阻塞,因为队列不受限制。

PriorityBlockingQueue不允许为空

Java中的PriorityBlockingQueue不允许使用null元素。尝试添加,放置或者提供null时,它将引发NullPointerException。

public class PriorityBQ {
  public static void main(String[] args) {
    BlockingQueue bQueue = new PriorityBlockingQueue<>();	
    // putting null
    bQueue.add(null);
  }
}

输出:

Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:480)
	at java.base/java.util.concurrent.PriorityBlockingQueue.add(PriorityBlockingQueue.java:464)
	at com.theitroad.programs.PriorityBQ.main(PriorityBQ.java:11)

PriorityBlockingQueue是一个有序队列

Java中PriorityBlockingQueue的主要功能是可以对该队列中的元素进行优先级排序。 PriorityBlockingQueue的元素是根据其自然顺序进行排序的,或者由队列构造时提供的Comparator进行排序,具体取决于所使用的构造函数。通过按照我们自己的比较逻辑对元素进行排序,可以对优先级队列中的元素进行优先级排序。依赖自然顺序的优先级队列也不允许插入不可比较的对象(这样做会导致ClassCastException)。

就指定的顺序而言,此队列的头是最小的元素。队列检索操作将轮询,删除,查看和访问元素,并访问队列开头的元素。

如果多个元素具有相同的优先级,则头部是那些元素之一,即关系被任意打破。

例如

public class PriorityBQ {
  public static void main(String[] args) {
    BlockingQueue<Integer> bQueue = new PriorityBlockingQueue<>();    
    // adding elements
    bQueue.add(10);
    bQueue.add(5);
    bQueue.add(1);
    bQueue.add(3);
    // retrieving (element at head of the queue)        
    System.out.println("Element- " + bQueue.poll());
  }
}

输出:

Element- 1

如我们所见,此处未指定Comparator,因此对Integer的自然排序(升序)用于对PriorityBlockingQueue中的元素进行排序。

具有比较器的PriorityBlockingQueue

这是另一个Java示例,其中指定了Comparator来对PriorityBlockingQueue中的元素进行排序(降序)。

public class PriorityBQ {
  public static void main(String[] args) {
    BlockingQueue<Integer> bQueue = new PriorityBlockingQueue<>(10, new MyComparator());    
    // adding elements
    bQueue.add(10);
    bQueue.add(5);
    bQueue.add(1);
    bQueue.add(3);
    // retrieving (head of the queue)        
    System.out.println("Element- " + bQueue.poll());
  }
}
//Comparator class
class MyComparator implements Comparator<Integer>{
  @Override
  public int compare(Integer o1, Integer o2) {
    return o2.compareTo(o1);
  }    
}

输出:

Element- 10

使用Java中的PriorityBlockingQueue的生产者使用者实现

BlockingQueue实现被设计为主要用于生产者-消费者队列,因此让我们来看一个使用PriorityBlockingQueue的生产者-消费者示例。在示例中,创建了两个线程,一个是生产者线程,另一个是消费者线程。

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

public class PriorityBQ {
  public static void main(String[] args) {
    BlockingQueue<String> bQueue = new PriorityBlockingQueue<>(10);    
    String[] Names = {"Krishna", "Madhusudan", "Muralidhar", "Jagannath"};
    // Producer 
    new Thread(()->{
      for(int i = 0; i < Names.length; i++){
        try {
          bQueue.put(Names[i]);
          System.out.println("Added to queue-" + Names[i]);                
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }).start();
        
    // Consumer
    new Thread(()->{
      for(int i = 0; i < Names.length; i++){
        try {
          System.out.println("Consumer retrieved- " + bQueue.take());					
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }).start();
  }
}

输出:

Added to queue-Krishna
Added to queue-Madhusudan
Added to queue-Muralidhar
Added to queue-Jagannath
Consumer retrieved- Jagannath
Consumer retrieved- Krishna
Consumer retrieved- Madhusudan
Consumer retrieved- Muralidhar