jdk优先级队列源码分析

1 jdk PriorityQueue简述

上文讲述了netty优先级队列的实现方式,本文将jdk1.8源码实现的优先级队列,做进一步比较和分析.

从下图继承关系可知,netty实现与jdk实现优先级队列原理类似,只是netty针对task做了更多特定的封装,而dk实现的PriorityQueue通用性更强;

在这里插入图片描述

2 jdk PriorityQueue基本组成

与netty实现类似,这里也是以数组实现堆结构来存储优先级队列!同样也存在比较器,方便用户灵活定义比较功能;

在这里插入图片描述

3 入队操作-offer分析

jdk实现的入队操作比netty实现更具有通用性,假如内置比较器为null,则会使用节点,强制转换为Comparable类型,使用该类型进行比较,其他具体操作除了部分细节不同外,基本上和netty的优先级队列实现差别不大!

//offer实现
    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;
    }
//siftUp实现
    private void siftUp(int k, E x) {
        if (comparator != null)
            siftUpUsingComparator(k, x);
        else
            siftUpComparable(k, x);
    }
//从下往上堆化
    @SuppressWarnings("unchecked")
    private void siftUpUsingComparator(int k, E x) {
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            Object e = queue[parent];
            if (comparator.compare(x, (E) e) >= 0)
                break;
            queue[k] = e;
            k = parent;
        }
        queue[k] = x;
    }

4 出队操作-push分析

出队操作原理与netty实现基本类似,也是先取堆顶元素,然后取最后一个节点,自顶而下与子节点进行比较,进行堆化操作!

//poll实现
@SuppressWarnings("unchecked")
    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;
    }
//siftDown实现
    private void siftDown(int k, E x) {
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }
//从上往下堆化
    @SuppressWarnings("unchecked")
    private void siftDownUsingComparator(int k, E x) {
        int half = size >>> 1;
        while (k < half) {
            int child = (k << 1) + 1;
            Object c = queue[child];
            int right = child + 1;
            if (right < size &&
                comparator.compare((E) c, (E) queue[right]) > 0)
                c = queue[child = right];
            if (comparator.compare(x, (E) c) <= 0)
                break;
            queue[k] = c;
            k = child;
        }
        queue[k] = x;
    }

5 本文小结

jdk实现的优先级队列本质与netty实现基本一致,均是使用数组构建小顶堆,插入则从下网上比较堆化,删除则取最后一个元素从上往下进行堆化处理!

总结一下,这里有如下几点值得学习的:

  1. 感受netty与jdk的优先级队列实现思路:基本思路一致,netty定制了scheculeTask的一些特殊行为,而jdk则在通用性下了更多的功夫;
  2. jdk实现中同样存在扩容问题,这里思路也与netty实现吻合;
  3. 为了保证容错性,当比较器为空时候,jdk实现会使用比较器接口强制转换队列的存储对象,这里的选择值得商榷,必须保证如果比较器未初始化,存储节点必须继承实现可比较接口!
发布了88 篇原创文章 · 获赞 16 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/xinquanv1/article/details/103060837
今日推荐