java并发编程(二十五)----(JUC集合)LinkedBlockingDeque和ConcurrentLinkedDeque介绍
Queue除了前面介绍的实现外,还有一种双向的Queue实现Deque。这种队列允许在队列头和尾部进行入队出队操作,因此在功能上比Queue显然要更复杂。
LinkedBlockingDeque
我们来看一下该类中的成员变量:
public class LinkedBlockingDeque<E>
extends AbstractQueue<E>
implements BlockingDeque<E>, java.io.Serializable {
private static final long serialVersionUID = -387911632671998426L;
static final class Node<E> {
E item;
Node<E> prev;
Node<E> next;
Node(E x) {
item = x;
}
}
transient Node<E> first;
transient Node<E> last;
private transient int count;
private final int capacity;
final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
}
有一个内部类Node,该类用来标记queue的节点,capacity最大为Integer.MAX_VALUE。然后使用了独占锁和条件机制来保证线程安全和进行阻塞控制。从上面的结构上我们可以看出:
- 要想支持阻塞功能,队列的容量一定是固定的,否则无法在入队的时候挂起线程。也就是capacity是final类型的。
- 既然是双向链表,每一个结点就需要前后两个引用,这样才能将所有元素串联起来,支持双向遍历。也即需要prev/next两个引用。
- 双向链表需要头尾同时操作,所以需要first/last两个节点,当然可以参考LinkedList那样采用一个节点的双向来完成,那样实现起来就稍微麻烦点。
- 既然要支持阻塞功能,就需要锁和条件变量来挂起线程。这里使用一个锁两个条件变量来完成此功能。
上面对LinkedBlockingDeque的结构做了说明,那么原理就很清晰了,无非是用一个独占锁来保持线程安全,然后用Condition来做阻塞操作。双向链表的操作大家都很熟悉就不做过多解释。
ConcurrentLinkedDeque
ConcurrentLinkedDeque是JSR166y中新增的一个无界并发Deque实现,基于已链接节点的、任选范围的双端队列。在迭代时,队列保持弱一致性,但不会抛出ConcurrentModificationException异常。
我们看一下类的成员变量:
public class ConcurrentLinkedDeque<E>
extends AbstractCollection<E>
implements Deque<E>, java.io.Serializable {
private transient volatile Node<E> head;
private transient volatile Node<E> tail;
private static final Node<Object> PREV_TERMINATOR, NEXT_TERMINATOR;
@SuppressWarnings("unchecked")
Node<E> prevTerminator() {
return (Node<E>) PREV_TERMINATOR;
}
@SuppressWarnings("unchecked")
Node<E> nextTerminator() {
return (Node<E>) NEXT_TERMINATOR;
}
}
我们看到成员变量里面有头节点和尾节点,然后是节点的引用PREV_TERMINATOR, NEXT_TERMINATOR,
双向链表的结构都是一样的。ConcurrentLinkedDeque不是阻塞队列所以没有用到条件原语。我们在成员变量里面没有看到使用ReentrantLock,因为所有的操作都是使用原子操作,避免了使用独占锁造成性能问题。
java并发编程(二十五)----(JUC集合)LinkedBlockingDeque和ConcurrentLinkedDeque介绍的更多相关文章
- java并发编程(十五)----(线程池)java线程池简介
好的软件设计不建议手动创建和销毁线程.线程的创建和销毁是非常耗 CPU 和内存的,因为这需要 JVM 和操作系统的参与.64位 JVM 默认线程栈是大小1 MB.这就是为什么说在请求频繁时为每个小的请 ...
- java并发编程(十)----JUC原子类介绍
今天我们来看一下JUC包中的原子类,所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程),原子操作可以是 ...
- java并发编程(十五)内存可见两种方式 加锁和volatile
1.volatile变量是一种稍弱的同步机制在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比synchronized关键字更轻量级的同步机制. ...
- java并发编程(十一)----(JUC原子类)基本类型介绍
上一节我们说到了基本原子类的简单介绍,这一节我们先来看一下基本类型: AtomicInteger, AtomicLong, AtomicBoolean.AtomicInteger和AtomicLong ...
- java并发编程笔记(五)——线程安全策略
java并发编程笔记(五)--线程安全策略 不可变得对象 不可变对象需要满足的条件 对象创建以后其状态就不能修改 对象所有的域都是final类型 对象是正确创建的(在对象创建期间,this引用没有逸出 ...
- Java并发编程二三事
Java并发编程二三事 转自我的Github 近日重新翻了一下<Java Concurrency in Practice>故以此文记之. 我觉得Java的并发可以从下面三个点去理解: * ...
- 聊聊高并发(二十五)解析java.util.concurrent各个组件(七) 理解Semaphore
前几篇分析了一下AQS的原理和实现.这篇拿Semaphore信号量做样例看看AQS实际是怎样使用的. Semaphore表示了一种能够同一时候有多个线程进入临界区的同步器,它维护了一个状态表示可用的票 ...
- 并发编程(十五)——定时器 ScheduledThreadPoolExecutor 实现原理与源码深度解析
在上一篇线程池的文章<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中从ThreadPoolExecutor源码分析了其运行机制.限于篇幅,留下了Scheduled ...
- Java并发(二十):线程本地变量ThreadLocal
ThreadLocal是一个本地线程副本变量工具类. 主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不同的 ...
随机推荐
- 寻觅Azure上的Athena和BigQuery (二):神奇的PolyBase
前情回顾 在“数据湖”概念与理论逐渐深入人心的今天,面向云存储的交互式查询这个需求场景显得愈发重要.这是因为原生的云存储(主要指S3这样的对象存储)既能够容纳大容量的明细数据,又能在性能和成本间取得一 ...
- 1.Solr安装与配置
1.Solr安装 1:安装 Tomcat,解压缩即可. 2:解压 solr. 3:把 solr 下的dist目录solr-4.10.3.war部署到 Tomcat\webapps下(去掉版本号). 4 ...
- Java内部类你真的会吗?
一.四种内部类 1.1.成员内部类 成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式: public class OuterAndInnerClass { public sta ...
- 从后端到前端之Vue(一)写个表格试试水
目录: 1.脚本式开发. 2.工程化开发 3.工程化和脚本的区别 4.来个table试试水 4,1.目标 4.2.思路 4.3.设计与编码 4.4.效果 5.业务分离 6.功能拓展——个性化设置 ...
- DataGrid通过DataSet保存为xml文件,并导入
做了个小的DataGrid通过DataSet保存为xml_测试,DataGrid通过DataSet保存为xml_测试,通过dataSet.writeXML()和dataSet.readXML()方法完 ...
- 《ElasticSearch6.x实战教程》之分词
第四章-分词 下雨天留客天留我不留 本打算先介绍"简单搜索",对ES的搜索有一个直观的感受.但在写的过程中发现分词无论如何都绕不过去.term查询,match查询都与分词息息相关, ...
- panic: time: missing Location in call to Time.In
docker容器发布go项目出现以下问题: panic: time: missing Location in call to Time.In COPY --from=build /usr/share/ ...
- Android 开发感想
18年从.net转行做安卓开发,现在已经过去一年多了.说一下感想和心得体会! 一.开始 说一下我的经厉,从毕业开始出来工作一直是从事.net方向的开发工作.一开始也是没什么经验,加上也没有其他手艺就找 ...
- UVA11988 【Broken Keyboard (a.k.a. Beiju Text)】:题解
题目链接:https://www.luogu.org/problemnew/show/UVA11988 这题虽说是和链表有关的模拟,但其实并不是很需要啊,但蒟蒻用了(说的好听是练手,说的难听是太弱), ...
- iconfontのsymbol的使用
iconfontのsymbol的使用 iconfont三种方式的优缺点 unicode 优点: 1.兼容性最好,支持ie6+ 2.支持按字体的方式去动态调整图标大小,颜色等等 缺点: 1.不支持多色图 ...