JDK源码分析之主要阻塞队列实现类PriorityBlockingQueue

PriorityBlockingQueue类也是实现阻塞队列的一种工具类,同Array BlockingQueue类和LinkedBlockingQueue一样,最为消息中间件的实现类。同步线程之间的消息。

如果要分析PriorityBlockingQueue就必须要看看PriorityQueue是如何实现的了。类PriorityQueue和类PriorityBlockingQueue都是用Object [ ] queue来实现队列中的元素的存

放,这一点和ArrayBlockingQueue类一样。而且阻塞队列类PriorityBlockingQueue的入列和出列操作都是使用一把同步锁,但是LinkedBlockingQueue类的入列和出列操作都是自己使用独立的一把锁。

PriorityBlockingQueue类还有一个与前两种阻塞队列类不同的地方是:PriorityBlockingQueue对数组queue存放的元素的排列顺序进行了管理,数组queue的第一个元素是最小的元素,因此每次取出来的元素都是最下的元素。queue数组满足在二叉树结构下,所有的子二叉树的根节点是在该树下的最小值。

简而言之,在二叉树结构下,数组元素在树的根节点到叶子节点路径中的所有节点的值都是有序排列的。


图:


PriorityBlockingQueue类的属性

    //存放队列元素的数组

    private transient Object[] queue;

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

    //维护数组排序的时候进行比较的比较子
    private transient Comparator<? super E> comparator;
    //获取队列资源的同步锁
    private final ReentrantLock lock;

    //锁获取条件
    private final Condition notEmpty;

PriorityBlockingQueue类使用的一些方法:

PriorityBlockingQueue类实际上就是比PriorityQueue类多了同步的功能。许多的入列算法和出列算法都是一样的,下面就只给出PriorityQueue类的函数,而

PriorityBlockingQueue类似方法读者自己进行分析,对比一下就会很简单了,你自己也会同时掌握两个类的使用。

PriorityQueue类出列操作

    //队列出列是获取并删除在数组的第一个元素位置,并将最后一个元素放在根节点位置,这个影响的只是二叉树的一条路径,然后对这条路径进行半冒泡修复
    public E poll() {
        if (size == 0)
            return null;
        int s = --size;
        modCount++;
        E result = (E) queue[0];
        E x = (E) queue[s];
        queue[s] = null;
        if (s != 0)
            siftDown(0, x);
        return result;
    }

PriorityBlockingQueue类出列操作

/**
     * Mechanics for poll().  Call only while holding lock.
     */
    private E extract() {
        E result;
        int n = size - 1;
        if (n < 0)
            result = null;
        else {
            Object[] array = queue;
            result = (E) array[0];
            E x = (E) array[n];
            array[n] = null;
            Comparator<? super E> cmp = comparator;
            if (cmp == null)
                siftDownComparable(0, x, array, n);
            else
                siftDownUsingComparator(0, x, array, n, cmp);
            size = n;
        }
        return result;
    }
PriorityQueue类的入列操作
   public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException();
        modCount++;
        int i = size;
        if (i >= queue.length)//如果队列长度超容量,就增容
            grow(i + 1);
        size = i + 1;
        if (i == 0)//队列为空时,直接插入队列
            queue[0] = e;
        else	   //如果队列中已经存在元素了,则插入元素后要维护队列的排序(变异堆排序)
            siftUp(i, e);
        return true;
    }
PriorityQueue类的出列操作
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        E result;
        try {
            while ( (result = extract()) == null)
                notEmpty.await();
        } finally {
            lock.unlock();
        }
        return result;
    }
对于这些队列的API就不做过多解释了,如果读者有兴趣可以去了解更多

Priority BlockingQueue类和PriorityQueue类的算法和数据结构以及思想都是一样的,下一章我将把PriorityQueue类的所有源码的注释分析发表出来,大家有兴趣可以阅

读下,注释是我对PriorityQueue类的理解。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

比特科技软件开发工作室

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值