阻塞队列之PriorityBlockingQueue源码分析

阻塞队列之PriorityBlockingQueue

上一篇文章笔主介绍了Java中的优先级队列,即PriorityQueue,了解了其内部的具体实现。今天,我们再来学习下Java中的优先级阻塞队列,即PriorityBlockingQueue。

PriorityBlockingQueue的定义

我们看下JDK中对的PriorityBlockingQueue定义,如下:

An unbounded {@linkplain BlockingQueue blocking queue} that uses the same ordering rules as class {@link PriorityQueue} and supplies blocking retrieval operations. While this queue is logically unbounded, attempted additions may fail due to resource exhaustion (causing {@code OutOfMemoryError}). This class does not permit {@code null} elements. A priority queue relying on {@linkplain Comparable natural ordering} also does not permit insertion of non-comparable objects (doing so results in {@code ClassCastException}).

PriorityBlockingQueue是与类PriorityQueue使用相同排序规则并且提供阻塞检索操作的无界阻塞队列。虽然此队列在逻辑上是无界的,但尝试添加元素时可能会失败,由于资源耗尽(导致OutOfMemoryError)。此队列不允许空的元素。依赖自然顺序排序的优先级队列也不允许插入不可比较的对象(这样做会导致ClassCastException)

Operations on this class make no guarantees about the ordering of elements with equal priority. If you need to enforce an
ordering, you can define custom classes or comparators that use a secondary key to break ties in primary priority values.

此类上的操作不能保证具有相同优先级的元素的顺序。如果需要强制有序,可以定义自定义类或比较器,使用辅助关键字来打破主要优先级的关系。

PriorityBlockingQueue类的特点

简单总结下,PriorityBlockingQueue有以下特点:

  • PriorityBlockingQueue是一个无界队列,没有容量限制。
  • PriorityBlockingQueue不允许插入空元素,如果提供了比较器,插入的元素就按照比较器排序。否则,按照自然顺序来排序。
  • PriorityBlockingQueue不能保证具有相同优先级的元素的顺序。

接下来,我们从源码的角度来认识下PriorityBlockingQueue。

PriorityBlockingQueue类的成员属性

PriorityBlockingQueue主要定义了以下成员属性,源码如下:

    //队列的默认初始容量
    private static final int DEFAULT_INITIAL_CAPACITY = 11;

    //数组的最大长度
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    //队列基于数组实现,用来放置元素的数组,元素的优先级通过堆排序实现
    private transient Object[] queue;

    //队列中的元素个数
    private transient int size;

    //元素排序使用的比较器,如果comparator为null,则使用自然排序
    private transient Comparator<? super E> comparator;

    //所有对队列的操作都需要使用此锁
    private final ReentrantLock lock;

    //非空条件对象,队列为空时移除元素的线程会被阻塞
    private final Condition notEmpty;

    //扩容时需要使用此乐观锁,CAS实现
    private transient volatile int allocationSpinLock;

    //序列化和反序列化时会用到此属性,为了兼容老版本,只有在序列化和反序列化时不为null
    private PriorityQueue<E> q;
   
    // 获取Unsafe类的实例,使用Unsafe类实例获取乐观锁
    private static final sun.misc.Unsafe UNSAFE;
    
    //乐观锁的偏移量
    private static final long allocationSpinLockOffset;

PriorityBlockingQueue类的UNSAFE和allocationSpinLockOffset是在静态代码块进行初始化的,源码如下:

    static {
        try {
            //初始化Unsafe类实例
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> k = PriorityBlockingQueue.class;
            allocationSpinLockOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("allocationSpinLock"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }
PriorityBlockingQueue类的构造方法

PriorityBlockingQueue提供了四种方式来构造阻塞队列,分别是:

  • 默认无参构造方法,既不指定队列的初始容量,也不指定比较器。
  • 指定初始容量的构造方法
  • 指定初始容量和比较器的构造方法
  • 使用给定集合构造队列的方法

构造方法的源码如下:

    //默认无参构造方法
   public PriorityBlockingQueue() {
        //使用默认初始容量,指定比较器为nul,插入的元素使用自然排序
        this(DEFAULT_INITIAL_CAPACITY, null);
    }

    //使用指定初始容量的构造方法
    public PriorityBlockingQueue(int initialCapacity) {
         //指定比较器为nul,插入的元素使用自然排序
        this(initialCapacity, null);
    }

    //使用指定初始容量和比较器的构造方法
    public PriorityBlockingQueue(int initialCapacity,
                                 Comparator<? super E> comparator) {
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.comparator = comparator;
        this.queue = new Object[initialCapacity];
    }

    //使用给定集合构造队列的方法
    public PriorityBlockingQueue(Collection<? extends E> c) {
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        //此字段标识堆是否已经有序
        boolean heapify = true; // true if not known to be in heap order
        //此字段标识是否需要筛查
        boolean screen = true;  // true if must screen for nulls
        if (c instanceof SortedSet<?>) { //如果是SortedSet类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值