Java PriorityBlockingQueue 特性

  • PriorityBlockingQueue 是一个无界队列并且动态增长。默认初始容量为“11”,可以在适当的构造函数中使用 initialCapacity 参数覆盖它。
  • 它提供阻塞检索操作。
  • 它不允许 NULL 对象。
  • 添加到 PriorityBlockingQueue 的对象必须是可比较的,否则它会抛出 ClassCastException
  • 优先级队列的对象默认按自然顺序排列。
  • Comparator 可用于队列中对象的自定义排序。
  • 优先级队列的头部是基于自然排序或者基于比较器排序的最少元素。当我们轮询队列时,它从队列中返回头对象。
  • 如果存在多个具有相同优先级的对象,则它可以随机轮询其中的任何一个。
  • PriorityBlockingQueue 是线程安全的。
  • 方法 iterator() 中提供的 Iterator 不能保证以任何特定顺序遍历 PriorityBlockingQueue 的元素。如果我们需要有序遍历,请考虑使用 Arrays.sort(pbq.toArray())。
  • DrainTo() 可用于按优先级顺序删除部分或者全部元素,并将它们放置在另一个集合中。

Java PriorityBlockingQueue 示例

Employee 类实现了 Comparable 接口,默认情况下,该接口使对象可以通过员工“id”字段进行比较。
让我们看看对象的排序如何影响 PriorityBlockingQueue 中的添加和删除操作。

public class Employee implements Comparable<Employee> {
    private Long id;
    private String name;
    private LocalDate dob;
    public Employee(Long id, String name, LocalDate dob) {
        super();
        this.id = id;
        this.name = name;
        this.dob = dob;
    }

    @Override
    public int compareTo(Employee emp) {
        return this.getId().compareTo(emp.getId());
    }
    //Getters and setters
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", dob=" + dob + "]";
    }
}

自然排序

Java PriorityBlockingQueue 示例,用于添加和查询基于自然顺序进行比较的元素。

PriorityBlockingQueue<Employee> PriorityBlockingQueue = new PriorityBlockingQueue<>();

PriorityBlockingQueue.add(new Employee(1l, "AAA", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(4l, "CCC", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(5l, "BBB", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(2l, "FFF", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(3l, "DDD", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(6l, "EEE", LocalDate.now()));
while(true) 
{
    Employee e = PriorityBlockingQueue.poll();
    System.out.println(e);

    if(e == null) break;
}

输出:

Employee [id=1, name=AAA, dob=2018-10-31]
Employee [id=2, name=FFF, dob=2018-10-31]
Employee [id=5, name=BBB, dob=2018-10-31]
Employee [id=4, name=CCC, dob=2018-10-31]
Employee [id=3, name=DDD, dob=2018-10-31]
Employee [id=6, name=EEE, dob=2018-10-31]

PriorityBlockingQueue 比较器示例

让我们使用基于 Java 8 lambda 的比较器语法重新定义自定义排序并验证结果。

我们正在使用构造函数 PriorityBlockingQueue(int initialCapacity, Comparator Comparator) 。

//Comparator for name field
Comparator<Employee> nameSorter = Comparator.comparing(Employee::getName);
PriorityBlockingQueue<Employee> PriorityBlockingQueue = new PriorityBlockingQueue<>( 11, nameSorter );

PriorityBlockingQueue.add(new Employee(1l, "AAA", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(4l, "CCC", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(5l, "BBB", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(2l, "FFF", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(3l, "DDD", LocalDate.now()));
PriorityBlockingQueue.add(new Employee(6l, "EEE", LocalDate.now()));
while(true) 
{
    Employee e = PriorityBlockingQueue.poll();
    System.out.println(e);

    if(e == null) break;
}

输出:

Employee [id=1, name=AAA, dob=2018-10-31]
Employee [id=5, name=BBB, dob=2018-10-31]
Employee [id=4, name=CCC, dob=2018-10-31]
Employee [id=3, name=DDD, dob=2018-10-31]
Employee [id=6, name=EEE, dob=2018-10-31]
Employee [id=2, name=FFF, dob=2018-10-31]

PriorityBlockingQueuedrainTo() 示例

使用drianTo() 方法在一个语句中从队列中获取多个元素的Java 示例。

PriorityBlockingQueue<Integer> priorityBlockingQueue = new PriorityBlockingQueue<>();

priorityBlockingQueue.add(1);
priorityBlockingQueue.add(3);
priorityBlockingQueue.add(2);
priorityBlockingQueue.add(6);
priorityBlockingQueue.add(4);
priorityBlockingQueue.add(5);
ArrayList<Integer> list = new ArrayList<>();
//移除前3个元素
priorityBlockingQueue.drainTo(list, 3);
System.out.println(list);

//移除所有元素
priorityBlockingQueue.drainTo(list);
System.out.println(list);

输出:

[1, 2, 3]
[1, 2, 3, 4, 5, 6]

PriorityBlockingQueue 阻塞检索示例

示例:使用阻塞检索从 PriorityBlockingQueue 中获取元素。
线程将等待,直到队列中存在元素。

在示例中,一个线程使用 take() 方法在无限循环中等待队列。
在再次检查之前等待 1 秒钟。
一旦我们向队列添加元素,它就会轮询项目并打印到控制台。

import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
public class PriorityQueueExample 
{
    public static void main(String[] args) throws InterruptedException 
    {
        PriorityBlockingQueue<Integer> priorityBlockingQueue = new PriorityBlockingQueue<>();

        new Thread(() -> 
        {
          System.out.println("Waiting to poll ...");

          try 
          {
              while(true) 
              {
                  Integer poll = priorityBlockingQueue.take();
                  System.out.println("Polled : " + poll);
                  Thread.sleep(TimeUnit.SECONDS.toMillis(1));
              }

          } catch (InterruptedException e) {
              e.printStackTrace();
          }

        }).start();

        Thread.sleep(TimeUnit.SECONDS.toMillis(2));
        priorityBlockingQueue.add(1);

        Thread.sleep(TimeUnit.SECONDS.toMillis(2));
        priorityBlockingQueue.add(2);

        Thread.sleep(TimeUnit.SECONDS.toMillis(2));
        priorityBlockingQueue.add(3);
    }
}

输出:

Waiting to poll ...
Polled : 1
Polled : 2
Polled : 3

Java PriorityBlockingQueue 的方法

  • boolean add(object) :将指定元素插入此优先级队列。
  • boolean offer(object) :将指定的元素插入此优先级队列。
  • boolean remove(object) :从此队列中移除指定元素的单个实例(如果存在)。
  • Object poll() :检索并删除此队列的头部,如果需要元素可用,则等待指定的等待时间。
  • Object poll(timeout, timeUnit) :检索并删除此队列的头部,如果需要元素可用,则等待指定的等待时间。
  • Object take() :检索并移除此队列的头部,必要时等待元素变为可用。
  • void put(Object o) :将指定元素插入此优先级队列。
  • void clear() :从此优先级队列中删除所有元素。
  • Comparator Comparator() :返回用于对该队列中的元素进行排序的比较器,如果该队列根据其元素的自然顺序进行排序,则返回 null。
  • boolean contains(Object o) :如果此队列包含指定的元素,则返回 true。
  • Iterator iterator() :返回此队列中元素的迭代器。
  • int size() :返回此队列中的元素数。
  • int DrainTo(Collection c) :从此队列中移除所有可用元素并将它们添加到给定集合中。
  • int DrainTo(Collection c, int maxElements) :最多从此队列中移除给定数量的可用元素,并将它们添加到给定的集合中。
  • int resumeCapacity() :总是返回 Integer.MAX_VALUE,因为 PriorityBlockingQueue 不受容量限制。
  • Object[] toArray() :返回一个包含此队列中所有元素的数组。

请注意 take() 和 poll() 方法之间的区别。
poll() 检索并删除此队列的头部,如果此队列为空,则返回 null。
它不是阻塞操作。

take() 检索并删除此队列的头部,必要时等待元素变为可用。
它是阻塞操作。

on  it road.com

Java PriorityBlockingQueue 的构造函数

PriorityBlockingQueue 类提供了 4 种不同的方式来构造 Java 中的优先级队列。

  • PriorityBlockingQueue() :构造具有默认初始容量 (11) 的空队列,该队列根据元素的自然顺序对其进行排序。
  • PriorityBlockingQueue(Collection c) :构造包含指定集合中元素的空队列。
  • PriorityBlockingQueue(int initialCapacity) :构造具有指定初始容量的空队列,该队列根据元素的自然顺序对其元素进行排序。
  • PriorityBlockingQueue(int initialCapacity, Comparator Comparator) :构造具有指定初始容量的空队列,根据指定的比较器对其元素进行排序。
Java PriorityBlockingQueue

Java PriorityBlockingQueue 类是并发阻塞队列数据结构实现,其中对象根据其优先级进行处理。

在优先级阻塞队列中,添加的对象根据它们的优先级排序。
默认情况下,优先级由对象的自然顺序决定。
默认优先级可以被队列构建时提供的 Comparator 覆盖。

日期:2020-09-17 00:09:48 来源:oir作者:oir