java+arrayblockquene_Java源码分析-ArrayBlockingQueue
ArrayBlockingQueue是JDK1.5开始concurrent包中提供的并发工具类,是一个基于数组的有界的先进先出队列,如果加入元素时,数组已满,或数组为空时,取元素都会阻塞当前线程,是一个典型的生产者消费者模式。类似的类还有LinkedBlockingQueue,PriorityBlockingQueue。
继承关系
public class ArrayBlockingQueue extends AbstractQueue
implements BlockingQueue, java.io.Serializable
public interface BlockingQueue extends Queue
核心成员变量
final Object[] items; //保存元素
/** items index for next take, poll, peek or remove */
int takeIndex; //指向队头
/** items index for next put, offer, or add */
int putIndex; //指向队尾
/** Number of elements in the queue */
int count; //队中元素计数
/*
* Concurrency control uses the classic two-condition algorithm
* found in any textbook.
*/
/** Main lock guarding all access */
final ReentrantLock lock; //可重入锁
/** Condition for waiting takes */
private final Condition notEmpty; //条件变量
/** Condition for waiting puts */
private final Condition notFull; //条件变量
构造方法
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity]; //初始化指定大小的有界队列
lock = new ReentrantLock(fair); //fair指示该锁是否是公平的
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
添加元素:put方法
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await(); //添加元素时,如果已满,则阻塞当前线程,等待在notFull这个条件变量上,等待notFull调用signal唤醒
enqueue(e); //此时队列肯定未满
} finally {
lock.unlock();
}
}
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
final Object[] items = this.items;
items[putIndex] = x; //将元素加入队尾
if (++putIndex == items.length) //将putIndex加1,如果到达数组尾部,则从0开始
putIndex = 0;
count++; //增加计数
notEmpty.signal(); //增加一个元素后,如果有线程等待在noEmpty条件变量上,通知并唤醒一种一个线程。
}
put方法首先判断队列是否已满,如果已满,则阻塞当前线程,等待在notFull这个条件变量上,等待notFull调用signal唤醒。当队列非空时,将该元素加入队尾,增加元素计数,唤醒因为进行去操作时数组为空而等待在notEmpty上的线程,通知它此时队列已经有元素了,你可以进行取操作了。
取元素:take方法
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await(); //取元素但是队列为空时,阻塞线程,等待在notEmpty上
return dequeue(); //此时,队列肯定非空,进行出队操作
} finally {
lock.unlock();
}
}
private E dequeue() {
// assert lock.getHoldCount() == 1;
// assert items[takeIndex] != null;
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex]; //获取队头元素
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--; //计数减1
if (itrs != null)
itrs.elementDequeued();
notFull.signal(); //通知因为添加元素但是队列已满时而阻塞的线程,队列此时可插入了
return x; //返回队头元素
}
take方法和put方法类似,先检查队列是否为空,队列为空时,阻塞线程,等待在notEmpty上。当队列非空时,进行出队操作。同时还要通知因为添加元素但是队列已满时而阻塞的线程,队列此时可插入了。
java+arrayblockquene_Java源码分析-ArrayBlockingQueue相关推荐
- java web开源项目源码_超赞!推荐一个专注于Java后端源码分析的Github项目!
大家好,最近有小伙伴们建议我把源码分析文章及源码分析项目(带注释版)放到github上,这样小伙伴们就可以把带中文注释的源码项目下载到自己本地电脑,结合源码分析文章自己本地调试,总之对于学习开源项目源 ...
- Java集合源码分析(二)ArrayList
ArrayList简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线 ...
- Java IO源码分析(四)——PrintStream
简介 PrintStream继承于FilterOutputStream,而FilterOutputStream用于封装其他的输出流. PrintStream用于给其他的输出流封装了一层打印的功能,它内 ...
- java abstractlist_源码分析-java-AbstractList-Itr和ListItr的实现
AbstractList API文档 AbstractList实现了List接口,又因为List继承自Collection,Collection继承自Iterable.因此List接口包含很多的方法. ...
- Java Stream源码分析及知识点总结
概述 什么是Stream Stream就是一种流式的处理数据风格,这一种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如进行筛选.排序和聚合.通俗地说,就是将St ...
- 【java】java boolean 源码分析
1.概述 转载:jdk源码分析-------------boolean 这篇文章小编只是对boolean类型的几个方法进行一次知识梳理,大家有好的意见可以在留言区留下宝贵的意见,小编会做出相应的调整. ...
- Java 容器源码分析之 TreeMap
TreeMap 是一种基于红黑树实现的 Key-Value 结构.在使用集合视图在 HashMap 中迭代时,是不能保证迭代顺序的: LinkedHashMap 使用了双向链表,保证按照插入顺序或者访 ...
- java编译器源码分析之语法分析器
token流到抽象语法树的过程是语法分析. 前面认识到token流,这部分将介绍抽象语法树(AST). 那么什么是抽象语法树(AST)?AST长啥样?我们的token流是如何转变成AST的?下面围绕这 ...
- java 反编译器源码分析
简介 由于工作需要反编译分析 java 源码,于是需要反编译器做些改动,所以就有了这篇文章. 这次要分析的反编译器是 Femflower,是著名 IDE Idea 的反编译器.源码也是从 Idea 开 ...
最新文章
- 导入语句 python_Python导入语句说明
- 全栈必备Linux 基础
- POJ1178枚举三个地方(所有点都去同一个点)
- MyBatis——@Result注解column参数传递——父查询函数的参数传递到子查询
- C语言不用循环不用递归打印0-999的小程序,你看懂了吗?
- 如何实现手游app瘦身?
- mysql bin.000047_mysql-bin.0000X 日志文件处理
- 改善 Python 程序的 91 个建议
- 一个年轻的码农的一个C#项目
- 浏览器兼容性问题——IE不支持却很实用的CSS属性Outline和Child
- 简单使用mybatis(idea中使用)
- 超级简单Python学生信息管理系统设计与实现.zip(论文+项目源码+使用说明书)
- mo汇编指令_汇编指令(汇编指令详解)
- 图解机器学习算法(8) | 回归树模型详解(机器学习通关指南·完结)
- LeetCode-Python-1386. 安排电影院座位(数组)
- Unity Editor 判断在哪个视图选中对象(Hierachy, Porject)
- android 菜鸟面单打印_android菜鸟 实战项目之简单界面实现
- iOS审核被拒含义及应对措施-长文
- python if简洁写法_Python - if-else 的多种简洁写法
- SQLserver获取汉字的拼音码和五笔码