LinkedBlockingQueue 源码学习

来源:互联网 发布:衣服在线设计软件 编辑:程序博客网 时间:2024/05/08 18:03

LinkedBlockingQueue是一个由单向链表实现的阻塞队列,该队列按照先进先出的原则对元素进行排序。队尾插入元素,对头删除元素。在构造LinkedBlockingQueue时可以指定容量大小,若未指定元素,则容量大小为Integer.MAX_VALUE.

1.以下为LinkedBlockingQueue的属性

   static class Node<E> {//链表中节点的定义        E item;        /**         * One of:         * - the real successor Node         * - this Node, meaning the successor is head.next         * - null, meaning there is no successor (this is the last node)         */        Node<E> next;        Node(E x) { item = x; }    }    /** The capacity bound, or Integer.MAX_VALUE if none */    private final int capacity;    /** Current number of elements */    private final AtomicInteger count = new AtomicInteger(0);//队列中元素的个数    /**     * Head of linked list.     * Invariant: head.item == null     */    private transient Node<E> head;//头节点,    /**     * Tail of linked list.     * Invariant: last.next == null     */    private transient Node<E> last;//尾节点    /** Lock held by take, poll, etc */    private final ReentrantLock takeLock = new ReentrantLock();//取出锁    /** Wait queue for waiting takes */    private final Condition notEmpty = takeLock.newCondition();//非空条件    /** Lock held by put, offer, etc */    private final ReentrantLock putLock = new ReentrantLock();//插入锁    /** Wait queue for waiting puts */    private final Condition notFull = putLock.newCondition();//非满条件
LinkedBlockingQueue采用两把锁,takeLock和putLock .对插入元素和取出元素采用不同的锁,提高并发性。


以下主要分析put与take操作

2.put函数源码分析:

 public void put(E e) throws InterruptedException {        if (e == null) throw new NullPointerException();        // Note: convention in all put/take/etc is to preset local var        // holding count negative to indicate failure unless set.        int c = -1;        Node<E> node = new Node(e);//插入元素时会new 出一个Node对象,影响性能        final ReentrantLock putLock = this.putLock;//使用putLock锁进行互斥操作        final AtomicInteger count = this.count;        putLock.lockInterruptibly();        try {            /*             * Note that count is used in wait guard even though it is             * not protected by lock. This works because count can             * only decrease at this point (all other puts are shut             * out by lock), and we (or some other waiting put) are             * signalled if it ever changes from capacity. Similarly             * for all other uses of count in other wait guards.             */            while (count.get() == capacity) {//当队列满时,线程阻塞与notFull条件变量                notFull.await();            }            enqueue(node);//插入元素node            c = count.getAndIncrement();//把在执行插入元素操作之前的队列元素个数赋给c ,count再增一            if (c + 1 < capacity)//如果在插入元素之后,队列元素的个数小于capacity,说明队列还可以执行Put操作,本put
                                 //本put线程唤醒其他被阻塞的put线程                notFull.signal();        } finally {            putLock.unlock();        }        if (c == 0)//在插入此元素之前若c为零,说明可能会有take线程被阻塞,则唤醒被阻塞的take线程            signalNotEmpty();    }
 private void signalNotEmpty() {        final ReentrantLock takeLock = this.takeLock;        takeLock.lock();        try {            notEmpty.signal();        } finally {            takeLock.unlock();        }    }

3.take()源码分析

  public E take() throws InterruptedException {        E x;        int c = -1;        final AtomicInteger count = this.count;        final ReentrantLock takeLock = this.takeLock;//采用takeLock        takeLock.lockInterruptibly();        try {            while (count.get() == 0) {//当队列为空时,take线程阻塞                notEmpty.await();            }            x = dequeue();            c = count.getAndDecrement();//获得执行删除元素之前,队列中元素的个数            if (c > 1)//若c>1说明队列中还有元素 ,则唤醒被阻塞的take线程                notEmpty.signal();        } finally {            takeLock.unlock();        }        if (c == capacity)//在删除元素之前,队列已满,唤醒被阻塞的put线程            signalNotFull();        return x;    }

 private void signalNotFull() {        final ReentrantLock putLock = this.putLock;        putLock.lock();        try {            notFull.signal();        } finally {            putLock.unlock();        }    }



0 0
原创粉丝点击