面试准备--线程池队列 PriorityBlockingQueue 详解

最后一个线程池的阻塞队列了,写完这个线程池篇应该算是结束了。

PriorityBlockingQueue 队列是 JDK1.5 的时候出来的一个阻塞队列。但是该队列有个入队的时候是不会阻塞的,永远会加到队尾。下面我们介绍下它的几个特点:

  • PriorityBlockingQueue 和 ArrayBlockingQueue 一样是基于数组实现的,但后者在初始化时需要指定长度,前者默认长度是 11。
  • 该队列可以说是真正的无界队列,它在队列满的时候会进行扩容,而前面说的无界阻塞队列其实都有有界,只是界限太大可以忽略(最大值是 2147483647)
  • 该队列属于权重队列,可以理解为它可以进行排序,但是排序不是从小到大排或从大到小排,是基于数组的堆结构(具体如何排下面会进行分析)
  • 出队方式和前面的也不同,是根据权重来进行出队,和前面所说队列中那种先进先出或者先进后出方式不同。

注意:

  1. 堆结构实际上是一种完全二叉树,建议学习前了解一下二叉树。

  2. 堆又分为 大顶堆小顶堆。大顶堆中第一个元素肯定是所有元素中最大的,小顶堆中第一个元素是所有元素中最小的。

下面是 PriorityBlockingQueue 队列的类图:
在这里插入图片描述
阻塞队列基本都会实现 BlockingQueue 接口,就不介绍。下面我们直接进入源码来进行分析学习。先看看类中的几个字段:

	/**
	* 默认数组长度
	*/
	private static final int DEFAULT_INITIAL_CAPACITY = 11;

    /**
	 * 最大达容量,分配时超出可能会出现 OutOfMemoryError 异常
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
	 * 队列,存储我们的元素
     */
    private transient Object[] queue;

    /**
     * 队列长度
     */
    private transient int size;

    /**
     * 比较器,入队进行权重的比较
     */
    private transient Comparator<? super E> comparator;

    /**
     * 显示锁
     */
    private final ReentrantLock lock;
    
    /**
     * 空队列时进行线程阻塞的 Condition 对象
     */
    private final Condition notEmpty;

从上面的字段我们可以知道,该队列可以排序,使用显示锁来保证操作的原子性,在空队列时,出队线程会堵塞等。那大概可以猜测到会有哪些构造方法了。

	/**
	* 默认构造,使用长度为 11 的数组,比较器为空
	*/
 	public PriorityBlockingQueue() {
   
   
        this(DEFAULT_INITIAL_CAPACITY, null);
    }
	/**
	* 自定义数据长度构造,比较器为空
	*/
    public PriorityBlockingQueue(int initialCapacity) {
   
   
        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];
    }

下面我们来看下队列操作的核心方法。

入队方法:
下面可以看到 put 方法最终会调用 offer 方法,所以我们只看 offer 方法即可。

    public void put(E e)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值