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
- LinkedBlockingQueue 源码学习
- LinkedBlockingQueue学习
- Java集合源码学习(17)_BlockingQueue接口的实现LinkedBlockingQueue
- JDK并发工具类源码学习系列——LinkedBlockingQueue
- LinkedBlockingQueue源码解析
- LinkedBlockingQueue源码分析
- LinkedBlockingQueue源码阅读
- 源码分析-LinkedBlockingQueue
- LinkedBlockingQueue源码分析
- LinkedBlockingQueue源码解析
- LinkedBlockingQueue源码分析
- LinkedBlockingQueue源码分析
- LinkedBlockingQueue源码分析
- LinkedBlockingQueue源码讲解
- LinkedBlockingQueue的学习
- 队列LinkedBlockingQueue学习
- 队列学习之LinkedBlockingQueue
- JUC-LinkedBlockingQueue学习
- AE调用GP工具切图
- 多重背包问题
- Servlet3.0学习总结(二)——使用注解标注过滤器(Filter)
- MATLAB 方差函数 var std
- C++找对象的季节(补)——我的数组类
- LinkedBlockingQueue 源码学习
- tomcat 应用访问
- Servlet3.0学习总结(三)——基于Servlet3.0的文件上传
- IAR variable "l" was set but never used 错误分析
- 机器学习--基本问题定义,任务确定和概念理解
- C++ primer 读书笔记(第6章)函数
- 【leetcode with java】7 Reverse Integer
- 基于MATLAB中fft函数的时域采样信号频谱生成代码
- oracle11.2中分区功能测试之add&split partition对global&local index的影响