一丶什么是阻塞队列
阻塞队列 (BlockingQueue) 是一个支持两个可以进行阻塞插入和阻塞移除的附加方法的队列.
1)阻塞插入: 当队列满后, 队列会阻塞 (拒绝) 插入元素, 直到队列不满.
2)阻塞移除: 当队列为空时, 队列会阻塞 (拒绝) 移除元素, 直到队列里有元素.
二丶 JDK 提供的 7 个阻塞队列
ArrayBlockingQueue: 由数组结构组成的有界阻塞队列
LinkedBlockingQueue: 由链表结构组成的有界阻塞队列
PriorityBlockingQueue: 支持优先级排序的无界阻塞队列
DelayQueue: 使用优先级队列实现的无界阻塞队列
SynchronousQueue: 不存储元素的阻塞队列
LinkedTransferQueue: 由链表结构组成的无界阻塞队列
LinkedBlockingDeque: 由链表结构组成的双向阻塞队列
三丶阻塞队列的实现原理
介绍过阻塞队列后博主想到的第一个应用就是生产者和消费者场景, 阻塞队列是如何实现的, 那我们可以想象一下用一般的多线程是如何实现生产者和消费者场景的:
https://blog.csdn.net/qq_39266910/article/details/78145340
上面是博主以前看多线程编程核心一书敲得代码, 里面写就是用的 wait 和 notify 来实现生产者和消费者场景的, 同样, 在学习 ReentrantLock 的视乎也用来实现过生产者和消费者场景, 但是不同的是, 后者可以实现多生产者和多消费者的场景, 因为一个 Lock 可以有多个 Condition 对象不是吗?
如果理解了这些, 那么阻塞队列就更加不难理解了, 我们的阻塞队列就是利用 Condition 来实现的, 我们就拿 ArrayBlockingQueue 的 add 方法源码的看看吧:
首先这个是 ArrayBlockingQueue 的实现:
- public class ArrayBlockingQueue<E> extends AbstractQueue<E>
- implements BlockingQueue<E>, java.io.Serializable {
- ......
- }
- public boolean add(E e) {
- return super.add(e);
- }
这个直接继承了父类 AbstractQueue 的 add 方法, 那我们直接打开其父类的方法:
- public boolean add(E e) {
- if (offer(e))
- return true;
- else
- throw new IllegalStateException("Queue full");
- }
额... 可能我们还要打开 offer 方法:
小提示: 在 eclipse 中直接按 ctrl + 鼠标左键打开的是接口 Queue 的 offer 方法, 我们需要按 Ctrl+T, 然后可以发现 ArrayBlockingQueue 对这个 offer 方法进行实现了, 所以直接找到 ArrayBlockingQueue 里的 offer 方法:
- public boolean offer(E e) {
- checkNotNull(e);
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- if (count == items.length)
- return false;
- else {
- enqueue(e);
- return true;
- }
- } finally {
- lock.unlock();
- }
- }
以上的代码使用 enqueue 方法进行入队操作, 虽然这个时候我们还没看见 Condition, 但是我们已经看见了 ReentrantLock 了不是吗?
继续追源码:
- private void enqueue(E x) {
- // assert lock.getHoldCount() == 1;
- // assert items[putIndex] == null;
- final Object[] items = this.items;
- items[putIndex] = x;
- if (++putIndex == items.length)
- putIndex = 0;
- count++;
- notEmpty.signal();
- }
哈哈, 看到了这 notEmpty.signal(); 行代码, 我笑了, 哼, 我们直接打开 notEmpty, 然后发现:
- private final Condition notEmpty;
- private final Condition notFull;
看到了吧, 就是 Condition 对象来实现的.
我之所以不上来就把 ArrayBlockingQueue 的字段列上来, 然后分析, 是因为博主认为, 一样东西不要上来就看它的架构(对大多数人而言), 首先我们要会用, 然后再摸清楚它的构造, 就像汽车以上, 我们不都是会开车后, 然后车慢慢出问题了, 然后找方法去修理吗?
者可能是博主个人的学习方式, 大神可能就不适合我说的这种方式了.
关于阻塞队列底层实现真的不难(博主那么菜也能看的七分懂), 所以就不继续往下面看了, 至于其他几种阻塞队列的实现, 有空再拜读, 感兴趣的小伙伴也可以自己去看看, 应该能收获一些有用的知识!
- (写这篇文章的目的之一也是自己在看线程池, 原来只想简单罗列一下几个阻塞队列, 没想到写的多了一点, 当然也没有多太多, 嘿嘿)
- 2018 4.14 14:31
来源: https://www.cnblogs.com/MindMrWang/p/8831788.html