Java Review - 并发编程_LinkedBlockingQueue原理源码剖析
文章目录
- 概述
- 类图结构
- 主要方法
- offer操作
概述
Java Review - 并发编程_ConcurrentLinkedQueue原理&源码剖析
介绍了使用CAS算法实现的非阻塞队列ConcurrentLinkedQueue,下面我们来介绍使用独占锁实现的阻塞队列LinkedBlockingQueue
类图结构
首先看一下LinkedBlockingQueue的类图结构,以便从全局对LinkedBlockingQueue有个直观的了解
由类图可以看到,LinkedBlockingQueue也是使用单向链表实现的,其也有两个Node,分别用来存放首、尾节点,并且还有一个初始值为0的原子变量count,用来记录队列元素个数。
另外还有两个ReentrantLock的实例,分别用来控制元素入队和出队的原子性,其中takeLock用来控制同时只有一个线程可以从队列头获取元素,其他线程必须等待,putLock控制同时只能有一个线程可以获取锁,在队列尾部添加元素,其他线程必须等待
另外,notEmpty和notFull是条件变量,它们内部都有一个条件队列用来存放进队和出队时被阻塞的线程,其实这是生产者—消费者模型
/** Current number of elements */private final AtomicInteger count = new AtomicInteger();/*** Head of linked list.* Invariant: head.item == null*/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实例上执行take、 poll等操作时需要获取到takeLock锁,从而保证同时只有一个线程可以操作链表头节点。另外由于条件变量notEmpty内部的条件队列的维护使用的是takeLock的锁状态管理机制,所以在调用notEmpty的await和signal方法前调用线程必须先获取到takeLock锁,否则会抛出IllegalMonitorStateException异常。notEmpty内部则维护着一个条件队列,当线程获取到takeLock锁后调用notEmpty的await方法时,调用线程会被阻塞,然后该线程会被放到notEmpty内部的条件队列进行等待,直到有线程调用了notEmpty的signal方法。
在LinkedBlockingQueue实例上执行put、offer等操作时需要获取到putLock锁,从而保证同时只有一个线程可以操作链表尾节点。同样由于条件变量notFull内部的条件队列的维护使用的是putLock的锁状态管理机制,所以在调用notFull的await和signal方法前调用线程必须先获取到putLock锁,否则会抛出IllegalMonitorStateException异常。notFull内部则维护着一个条件队列,当线程获取到putLock锁后调用notFull的await方法时,调用线程会被阻塞,然后该线程会被放到notFull内部的条件队列进行等待,直到有线程调用了notFull的signal方法。
如下是LinkedBlockingQueue的无参构造函数的代码。
/*** A constant holding the maximum value an {@code int} can* have, 2<sup>31</sup>-1.*/@Native public static final int MAX_VALUE = 0x7fffffff;/*** Creates a {@code LinkedBlockingQueue} with a capacity of* {@link Integer#MAX_VALUE}.*/public LinkedBlockingQueue() {this(Integer.MAX_VALUE);}public LinkedBlockingQueue(int capacity) {if (capacity <= 0) throw new IllegalArgumentException();this.capacity = capacity;// 初始化首 尾节点,并让它指向哨兵节点last = head = new Node<E>(null);}
由该代码可知,默认队列容量为0x7fffffff,用户也可以自己指定容量,所以从一定程度上可以说LinkedBlockingQueue是有界阻塞队列。
主要方法
offer操作
Java Review - 并发编程_LinkedBlockingQueue原理源码剖析相关推荐
- Java Review - 并发编程_ArrayBlockingQueue原理源码剖析
文章目录 概述 类图结构 构造函数 主要方法源码解析 offer操作 put操作 poll操作 take操作 peek操作 size 小结 概述 Java Review - 并发编程_LinkedBl ...
- Java Review - 并发编程_ScheduledThreadPoolExecutor原理源码剖析
文章目录 概述 类结构 核心方法&源码解析 schedule(Runnable command, long delay,TimeUnit unit) scheduleWithFixedDela ...
- Java Review - 并发编程_DelayQueue原理源码剖析
文章目录 概述 类图结构 小Demo 核心方法&源码解读 offer操作 take操作 poll操作 size操作 小结 概述 DelayQueue并发队列是一个无界阻塞延迟队列,队列中的每个 ...
- Java Review - 并发编程_ThreadPoolExecutor原理源码剖析
文章目录 线程池主要解决两个问题 类关系图 ctl 含义 ---- 记录线程池状态和线程池中线程个数 线程池状态 及转换 线程池参数 线程池类型 mainLock & termination ...
- Java Review - 并发编程_ConcurrentLinkedQueue原理源码剖析
文章目录 概述 ConcurrentLinkedQueue 核心方法&源码解读 offer add poll peek size remove contains 总结 概述 JDK中提供了一系 ...
- Java Review - 并发编程_PriorityBlockingQueue原理源码剖析
文章目录 概述 类图结构 小Demo 核心方法&源码解析 offer poll put take size 概述 PriorityBlockingQueue是带优先级的无界阻塞队列,每次出队都 ...
- Java Review - 并发编程_原子操作类原理剖析
文章目录 概述 原子变量操作类 主要方法 incrementAndGet .decrementAndGet .getAndIncrement.getAndDecrement boolean compa ...
- Java Review - 并发编程_原子操作类LongAdder LongAccumulator剖析
文章目录 概述 小Demo 源码分析 重要的方法 long sum() reset sumThenReset longValue() add(long x) longAccumulate(long x ...
- Java Review - 并发编程_ 回环屏障CyclicBarrier原理源码剖析
文章目录 Pre 小Demo 类图结构 CyclicBarrier核心方法源码解读 int await() int await(long timeout, TimeUnit unit) int dow ...
最新文章
- .NET平台BigO算法复杂度备忘
- BZOJ2437 [Noi2011]兔兔与蛋蛋 【博弈论 + 二分图匹配】
- python学习三:列表,元组
- SQL Server事务
- android studio scala插件,Scala 语言开发Andorid ,开发环境的搭建(一)
- android 监听手机电量变化
- pytorch实现L2和L1正则化regularization的方法
- 基于.NET CORE微服务框架 -谈谈surging API网关
- mybatis3中@SelectProvider的使用技巧
- Storm任务提交过程及目录树介绍
- mysql视图使用方法
- java sublist_java中的subList
- PPPoE原理和实验
- Quartz 触发器、过期触发策略 、排它日历、数据持久化
- 利用windbg分析程序崩溃生成的dmp文件
- DEM高程数据的获取和应用(全国DEM数据可直接下载)
- php redis入门指南,redis入门指南(四)—— redis如何节省空间
- 【聚焦群落生态学】统计方法回归和混合效应模型、多元统计分析技术及结构方程等数量分析方法
- 安卓游戏 我叫mt 3.5.4.0 3540,data.dat 文件解包记录
- 今天身边的一个好友想的一个点子,可能会颠覆传统电商网,称为线上商店和线下商店的最后收割者
热门文章
- lzw编码过程详解_编码拓展——封装、编码、码率
- 双代号网络图节点编号原则_『干货』二级建造师考试高频考点 双代号网络图的详细解析...
- mpvue 微信小程序api_第三方框架与原生微信小程序开发框架性能之比较 | Q荐读...
- 无源定位之时差估计的精确时差估计算法(ETDE)及MATLAB实现程序
- 有负权重边的图可以有拉普拉斯矩阵吗?
- 数据中台应用实战50篇(二)-中台解决方案本质在解决什么问题?
- tableau可视化数据分析60讲(二十)-tableau格式设置
- 图像处理特征不变算子系列之KLT算子
- 非负矩阵分解中基于L1和L2范式的稀疏性约束
- 数据分析利器--Pandas