ArrayBlockingQueue源码分析
ArrayBlockingQueue是一个基于数组实现的有界的阻塞队列。
属性
//底层存储元素的数组。为final说明一旦初始化,容量不可变,所以是有界的。
final Object[] items; //下一个take, poll, peek or remove操作的index位置
int takeIndex; //下一个put, offer, or add操作的index位置
int putIndex; // 元素数量
int count; /**
* 用于并发控制:使用经典的双Condition算法
*/
final ReentrantLock lock;
/** 获取操作等待条件 */
private final Condition notEmpty;
/** 插入操作等待条件 */
private final Condition notFull;
添加操作
1.add操作(不常用)
add()是最原始的方法。当队列满时,会抛出IllegalStateException。
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");
}
2.offer操作
offer有两个版本。
不带超时版本:队列满时,直接返回false。
带超时版本:队列满时,阻塞直到队列可用。
public boolean offer(E e) {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
//队列已满,直接返回false
if (count == items.length)
return false;
else {//未满,则插入元素
insert(e);
return true;
}
} finally {
lock.unlock();
}
} /**offer,带超时版本**/
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException { checkNotNull(e);
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
//可中断加锁
lock.lockInterruptibly();
try {
//不停判断是否满了
while (count == items.length) {
//超时,则直接返回false
if (nanos <= 0)
return false;
//队列已满,则等待
nanos = notFull.awaitNanos(nanos);
}
//阻塞直到队列可用,则插入元素
insert(e);
return true;
} finally {
lock.unlock();
}
}
3.put操作
public void put(E e) throws InterruptedException {
//检查参数是否为null。为null则抛异常
checkNotNull(e);
final ReentrantLock lock = this.lock;
//加锁。可中断
lock.lockInterruptibly();
try {
//队列已满则一直等待,直到队列有可用空间
while (count == items.length)
notFull.await();//等待
//队列空闲时,插入元素
insert(e);
} finally {
//释放锁
lock.unlock();
}
}
删除操作
1.poll操作
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : extract();
} finally {
lock.unlock();
}
} private E extract() {
final Object[] items = this.items;
E x = this.<E>cast(items[takeIndex]);//强转
//删除
items[takeIndex] = null;
takeIndex = inc(takeIndex);
--count;
//通知
notFull.signal();
return x;
} /**poll,带超时版本**/
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0) {
if (nanos <= 0)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
return extract();
} finally {
lock.unlock();
}
}
2.take操作
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return extract();
} finally {
lock.unlock();
}
}
3.peek操作
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : itemAt(takeIndex);
} finally {
lock.unlock();
}
}
清空操作
public void clear() {
final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
//依次将所有元素设为null
for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
items[i] = null;
//count,putIndex,takeIndex都为0
count = 0;
putIndex = 0;
takeIndex = 0; notFull.signalAll();
} finally {
lock.unlock();
}
}
总结
BlockingQueue接口提供了3个添加元素方法。
- add:添加元素到队列里,添加成功返回true,如果队列已满则抛出IllegalStateException异常。不常用。
- offer:添加元素到队列里,添加成功返回true,如果队列已满添加失败,返回false
- put:添加元素到队列里,添加成功返回true,如果队列已满则阻塞直到队列可用
同时,BlockingQueue接口提供了3个获取(并删除)元素的方法。
- remove:
- poll:返回队列头部元素。队列为空时,返回null
- take:队列为空时,会阻塞直到有数据加入到队列中
ArrayBlockingQueue源码分析的更多相关文章
- java多线程系列(九)---ArrayBlockingQueue源码分析
java多线程系列(九)---ArrayBlockingQueue源码分析 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 j ...
- 死磕 java集合之ArrayBlockingQueue源码分析
问题 (1)ArrayBlockingQueue的实现方式? (2)ArrayBlockingQueue是否需要扩容? (3)ArrayBlockingQueue有什么缺点? 简介 ArrayBloc ...
- 并发编程(八)—— Java 并发队列 BlockingQueue 实现之 ArrayBlockingQueue 源码分析
开篇先介绍下 BlockingQueue 这个接口的规则,后面再看其实现. 阻塞队列概要 阻塞队列与我们平常接触的普通队列(LinkedList或ArrayList等)的最大不同点,在于阻塞队列的阻塞 ...
- Java并发编程笔记之ArrayBlockingQueue源码分析
JDK 中基于数组的阻塞队列 ArrayBlockingQueue 原理剖析,ArrayBlockingQueue 内部如何基于一把独占锁以及对应的两个条件变量实现出入队操作的线程安全? 首先我们先大 ...
- 多线程高并发编程(12) -- 阻塞算法实现ArrayBlockingQueue源码分析(1)
一.前言 前文探究了非阻塞算法的实现ConcurrentLinkedQueue安全队列,也说明了阻塞算法实现的两种方式,使用一把锁(出队和入队同一把锁ArrayBlockingQueue)和两把锁(出 ...
- Java核心复习——J.U.C ArrayBlockingQueue源码分析
介绍 依赖关系 源码 构造方法 public ArrayBlockingQueue(int capacity) { this(capacity, false);//默认构造非公平的有界队列 } pub ...
- ArrayBlockingQueue 源码分析
ArrayBlockingQueue ArrayBlockingQueue 能解决什么问题?什么时候使用 ArrayBlockingQueue? 1)ArrayBlockingQueue 是底层由数组 ...
- 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)
一.前言 在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看Arra ...
- JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue
JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue 目的:本文通过分析JDK源码来对比ArrayBlockingQueue 和LinkedBlocki ...
随机推荐
- [深度概念]·K-Fold 交叉验证 (Cross-Validation)的理解与应用
K-Fold 交叉验证 (Cross-Validation)的理解与应用 我的网站 1.K-Fold 交叉验证概念 在机器学习建模过程中,通行的做法通常是将数据分为训练集和测试集.测试集是与训练独立的 ...
- 并发系列(2)之 ThreadLocal 详解
本文将主要结合源码讲述 ThreadLocal 的使用场景和内部结构,以及 ThreadLocalMap 的内部结构:另外在阅读文本之前只好先了解一下引用和 HashMap 的相关知识,可以参考 Re ...
- Flask的session使用
由于http是无状态保存的协议,session可以看作不同请求之间保存数据的一种机制.flask的session是基于cookie的会话保持. 流程 当客户端进行第一次请求的时候,客户端的HTTP r ...
- C#工具:WPF分页
1.使用ItemsControl控件 <UserControl x:Class="SunCreate.Vipf.Client.UI.CityDoor.PageControl" ...
- Ambiguous HTTP method Actions require an explicit HttpMethod binding for Swagger 2.0
异常内容 NotSupportedException: Ambiguous HTTP method for action . Actions require an explicit HttpMetho ...
- C# 曲线上的点(一) 获取指定横坐标对应的纵坐标值
获取直线上的点,很容易,那曲线呢?二阶贝塞尔.三阶贝塞尔.多段混合曲线,如何获取指定横坐标对应的纵坐标? 如下图形: 实现方案 曲线上的点集 Geometry提供了一个函数GetFlattenedPa ...
- QT5.6.0 VS2013 Win764位系统QT环境搭建过程
QT5.6.0 VS2013 Win764位系统QT环境搭建过程 没用过QT自己跟同事要了安装包,按照同事指导方法操作安装部署开发环境结果遇到好多问题,错误网上搜遍了所有帖子也没有找到合适的解决方案. ...
- 使用 phpstudy 搭建本地测试环境
最近在为另一个部门配置一个多语言的网站,因为之前他们已经做过 英文和中文两种语言,这次帮他们添加其它几种语言,从GitLab 上拉下来的代码,是php环境做的,需要在本地跑起来,做完测试通过后再一次性 ...
- spring boot整合Hadoop
最近需要用spring boot + mybatis整合hadoop,其中也有碰到一些坑,记录下来方便后面的人少走些弯路. 背景呢是因为需要在 web 中上传文件到 hdfs ,所以需要在spring ...
- 重庆3Shape CAMbridge都有哪些功能
三维打印技术创新领导者Objet Geometries公司和牙科领域三维扫描仪.CAD/CAM软件解决方案供应商3Shape A/S公司日前宣布两家公司合作研发的牙科领域三维修复解决方案已付诸实施.此 ...