Java中的阻塞队列

一丶什么是阻塞队列
阻塞队列(BlockingQueue)是一个支持两个可以进行阻塞插入阻塞移除的附加方法的队列。
1)阻塞插入:当队列满后,队列会阻塞(拒绝)插入元素,直到队列不满。
2)阻塞移除:当队列为空时,队列会阻塞(拒绝)移除元素,直到队列里有元素。


二丶JDK提供的7个阻塞队列

  1. ArrayBlockingQueue:由数组结构组成的有界阻塞队列
  2. LinkedBlockingQueue:由链表结构组成的有界阻塞队列
  3. PriorityBlockingQueue:支持优先级排序无界阻塞队列
  4. DelayQueue:使用优先级队列实现的无界阻塞队列
  5. SynchronousQueue:不存储元素的阻塞队列
  6. LinkedTransferQueue:由链表结构组成的无界阻塞队列
  7. 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

你可能感兴趣的:(Java多线程与并发)