zoukankan      html  css  js  c++  java
  • PriorityBlockingQueue 源码分析

      之前分析过ArrayBlockingQueue,它的特点是

      1 有限,不会扩容

      2 严格的先进先出

      今天要介绍的PriorityBlockingQueue,正好突破了这两点,第一它是无限的,第二它是根据元素的大小进行排序的的队列

      排序所使用的算法是堆排序,而且是小顶堆,也就是说值越小越优先

      补充一下,默认确实是小顶堆,但是构造方法提供了比较器,也可以实现大顶堆。

      

    public PriorityQueue(Comparator<? super E> comparator) {
        this(DEFAULT_INITIAL_CAPACITY, comparator);
    }
    
    
    PriorityQueue<Integer> queue = new PriorityQueue<>((num1, num2) -> num2 - num1);

    一 入队

    public boolean offer(E e) {
            if (e == null)
                throw new NullPointerException();
            final ReentrantLock lock = this.lock;
            lock.lock();
            int n, cap;
            Object[] array;
            while ((n = size) >= (cap = (array = queue).length))
                tryGrow(array, cap);//扩容,扩容的条件是size已经到头了 这个和hashmap可不一样
            try {
                Comparator<? super E> cmp = comparator;
                if (cmp == null)
                    siftUpComparable(n, e, array);//堆调整,n始终是当前的size
                else
                    siftUpUsingComparator(n, e, array, cmp);
                size = n + 1;//有lock包裹着不用加volatile
                notEmpty.signal();//唤醒等待线程
            } finally {
                lock.unlock();
            }
            return true;
        }
    private static <T> void siftUpComparable(int k, T x, Object[] array) {
            Comparable<? super T> key = (Comparable<? super T>) x;
            while (k > 0) {
                int parent = (k - 1) >>> 1;
                Object e = array[parent];
                if (key.compareTo((T) e) >= 0)
                    break;
                array[k] = e;
                k = parent;
            }
            array[k] = key;
        }

    入队就是从下到上,从右到左的找该元素应该所在的位置

    二 出队列

    public E poll() {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                return dequeue();
            } finally {
                lock.unlock();
            }
        }
    private E dequeue() {
            int n = size - 1;
            if (n < 0)
                return null;
            else {
                Object[] array = queue;
                E result = (E) array[0];//每次出队都是第0个
                E x = (E) array[n];//把当前的最后那个取出来缓存起来
                array[n] = null;
                Comparator<? super E> cmp = comparator;
                if (cmp == null)
                    siftDownComparable(0, x, array, n);//从0开始往下走,逐渐调整
                else
                    siftDownUsingComparator(0, x, array, n, cmp);
                size = n;
                return result;
            }
        }
    private static <T> void siftDownComparable(int k, T x, Object[] array,
                                                   int n) {
            if (n > 0) {
                Comparable<? super T> key = (Comparable<? super T>)x;
                int half = n >>> 1;           // loop while a non-leaf
                while (k < half) {
                    int child = (k << 1) + 1; // assume left child is least
                    Object c = array[child];
                    int right = child + 1;
                    if (right < n &&
                        ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
                        c = array[child = right];
                    if (key.compareTo((T) c) <= 0)
                        break;
                    array[k] = c;
                    k = child;
                }
                array[k] = key;
            }
        }

     出队列就是把堆头取出来,然后进行堆调整。

  • 相关阅读:
    wxpython的安装

    拓扑排序
    树,二叉树,森林,三者的转换
    二叉树的遍历
    最短路径
    图的遍历
    图的最小生成树
    哈夫曼树的应用
    哈夫曼树
  • 原文地址:https://www.cnblogs.com/juniorMa/p/14062791.html
Copyright © 2011-2022 走看看