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 ...
随机推荐
- Promise探讨
一.前言 大家都知道JavaScript一大特点就是单线程,为了不阻塞主线程,有些耗时操作(比如ajax)必须放在任务队列中异步执行.传统的异步编程解决方案之一回调,很容易产生臭名昭著的回调地狱问题. ...
- PMBook - 上课体会
一.上课感觉怎么样? 这两天都在培训PMP,第一天提前20分到的,空位很多,挑了第二排坐下,看投影效果挺好.第二天我提前30分钟到教室,中间的位置都坐满了,只能找其他位置了.看来大家积极性提高了很多, ...
- Sentinel 流程分析
最近公司开始做新的项目.新项目准备用点新的技术.之前我们采用的是spring cloud的那一套.之前几个月看到阿里开始拥抱springcloud,推出好几个组件无缝兼容现有springcloud.我 ...
- 前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战
一.组件化开发 1.1组件化概述 页面特效的制作,特别需要HTML.CSS有固定的布局,所以说现在越来越流行组件开发的模式,就是用JS写一个类,当你实例化这个类的时候,页面上的效果布局也能自动完成. ...
- 强化学习(三)用动态规划(DP)求解
在强化学习(二)马尔科夫决策过程(MDP)中,我们讨论了用马尔科夫假设来简化强化学习模型的复杂度,这一篇我们在马尔科夫假设和贝尔曼方程的基础上讨论使用动态规划(Dynamic Programming, ...
- SOFARPC源码解析-搭建环境
文档地址:https://www.sofastack.tech 简介摘要 SOFA 是蚂蚁金服自主研发的金融级分布式中间件,包含构建金融级云原生架构所需的各个组件,包括微服务研发框架,RPC 框架,服 ...
- [翻译] 使用 Python 创建你自己的 Shell:Part II
目录 使用 Python 创建你自己的 Shell:Part II 原文链接与说明 步骤 4:内置命令 最后的想法 使用 Python 创建你自己的 Shell:Part II 原文链接与说明 htt ...
- 清理dns缓存
dns缓存是什么? DNS缓存指DNS返回了正确的IP之后,系统就会将这个结果临时储存起来.并且它会为缓存设定一个失效时间 (例如N小时),在这N小时之内,当你再次访问这个网站时,系统就会直接从你电脑 ...
- JavaScript小记二则:接上一节:用.net写Textbox控件关于数字的判断的另一则方法
方法二.通过写JS进行判断控制输入的只能为数字,源码如下: <!DOCTYPE html> <html> <body> <h1></h1> ...
- css3动画--位移加阴影
animation: name duration timing-function delay iteration-count direction; 值 描述 animation-name 规定需要绑定 ...