zoukankan      html  css  js  c++  java
  • 学习BlockingQueue之PriorityBlockingQueue实现原理

    一:概念

      PriorityBlockingQueue 是一个支持优先级的无界阻塞队列。默认情况下元素 采取自然顺序升序排列。也可以自定义类实现 compareTo()方法来指定元素排序 规则,

    或者初始化 PriorityBlockingQueue 时,指定构造参数 Comparator 来对元素 进行排序。需要注意的是不能保证同优先级元素的顺序。

    二:示例

    main方法测试方法:

    生产者线程:

    消费者线程:

    通过输出结果可以看出数据在对列里面已经排序,所以消费者线程消费的时候是有序的。

    三:看一下PriorityBlockingQueue 这个类的源码

    默认容量 11

    数组最大分配值

     

     内部维护一个数组

    比较器,可以不初始化,但是对象必须具有比较性

     只有一把锁,锁所有的public操作

     

    看一下构造方法:

    入参有初始容量、比较器

     还可以初始化一个容器

    看一下offer和poll方法:

    offer方法:

    如果入参元素为null,则抛异常,  加锁,如果元素的数量等于数组的容量时,就要扩容;如果数组还有空间时,就会入队,

    入队会判断是否初始化比较器,如果有比较器,则按照比较器就行排序,没有,则元素必须具有可比较性

     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);
            try {
                Comparator<? super E> cmp = comparator;
                if (cmp == null)
                    siftUpComparable(n, e, array);
                else
                    siftUpUsingComparator(n, e, array, cmp);
                size = n + 1;
                notEmpty.signal();
            } finally {
                lock.unlock();
            }
            return true;
        }
    

      

    看一下扩容方法tryGrow

    poll方法:

    上锁,然后调用出队方法:

     public E poll() {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                return dequeue();
            } finally {
                lock.unlock();
            }
        }
    

      

    如果对列为空,则返回null,如果不为空,则把第一个元素返回,然后重新排序

     private E dequeue() {
            int n = size - 1;
            if (n < 0)
                return null;
            else {
                Object[] array = queue;
                E 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;
            }
        }
    

      

    add和remove方法:

    add方法的实现就是使用offer的逻辑

    remove方法:

    1:加锁  2:根据对象找到在数组中的索引 3:根据索引删除元素

    public boolean remove(Object o) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                int i = indexOf(o);
                if (i == -1)
                    return false;
                removeAt(i);
                return true;
            } finally {
                lock.unlock();
            }
        }
    

      

    根据对象寻找在数组中的下标位置

  • 相关阅读:
    基准测试工具 pgbench 之一初步测试
    postgresql 9.1 kernel.shm 设置不当导致 FATAL: could not create shared memory segment
    centos 6.8 + postgresql 9.6 + make
    plpgsql 执行块
    postgresql 10.1 分区表之 list 分区
    debian 各个版本的代号
    debian 8.2 bond 双网卡
    centos 6.8 + postgresql 9.6 + adminpack
    centos 6.8 + postgresql 9.6 + pldebugger/pldbgapi
    postgresql 10.1 参数的初步了解 Preset Options
  • 原文地址:https://www.cnblogs.com/warrior4236/p/12522840.html
Copyright © 2011-2022 走看看