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 ...
随机推荐
- 访问了一次百度网页,你都经历了什么?https及tcp协议揭秘
打开https://www.baidu.com/ 网页一个简单的动作,都经历了什么?你想探究内部的原理吗?那我们一起去探索吧 1.准备工作 安装好wireshark.Wireshark(前称Ether ...
- 并发系列(2)之 ThreadLocal 详解
本文将主要结合源码讲述 ThreadLocal 的使用场景和内部结构,以及 ThreadLocalMap 的内部结构:另外在阅读文本之前只好先了解一下引用和 HashMap 的相关知识,可以参考 Re ...
- Linux高级命令进阶(week1_day2)--技术流ken
输出重定向 场景:一般命令的输出都会显示在终端中,有些时候需要将一些命令的执行结果想要保存到文件中进行后续的分析/统计,则这时候需要使用到的输出重定向技术. >:覆盖输出,会覆盖掉原先的文件内容 ...
- 创建索引CreateIndex
nuget引用NEST new一个客户端 源码可查ElasticClient.cs new一个ElasticClient有多种方式 第一种 ES地址是http://localhost:9200,可以直 ...
- Jquery简单学习
Jquery是一个JavaScript的函数库,Jquery是一个写得少但做的多的轻量级JavaScript库 Jquery用美元$定义. Jquery的action执行对元素的操作 文档就绪函数: ...
- .net接收post请求,并转为字符串
Stream s = Request.InputStream; int count = 0; byte[] buffer = new byte[1024]; StringBuilder reqXml ...
- 折腾Java设计模式之迭代器模式
迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its ...
- web服务器负载均衡与集群基本概念二
前面已经说过负载均衡的作用是在多个节点之间按照一定的策略(算法)分发网络或计算处理负载.负载均衡可以采用软件和硬件来实现.一般的框架结构可以参考下图. 后台的多个Web节点上面有相同的Web应用 ...
- Aspnet mvc移除WebFormViewEngine
为了提高mvc的速度,在Global.asax中移除WebFormViewEngine protected void Application_Start() { RemoveWebFormEngine ...
- Jdk 接口类RandomAccess了解
1. 接口说明 Marker interface used by List implementations to indicate that they support fast (generally ...