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。然后使用了独占锁和条件机制来保证线程安全和进行阻塞控制。从上面的结构上我们可以看出:

  1. 要想支持阻塞功能,队列的容量一定是固定的,否则无法在入队的时候挂起线程。也就是capacity是final类型的。
  2. 既然是双向链表,每一个结点就需要前后两个引用,这样才能将所有元素串联起来,支持双向遍历。也即需要prev/next两个引用。
  3. 双向链表需要头尾同时操作,所以需要first/last两个节点,当然可以参考LinkedList那样采用一个节点的双向来完成,那样实现起来就稍微麻烦点。
  4. 既然要支持阻塞功能,就需要锁和条件变量来挂起线程。这里使用一个锁两个条件变量来完成此功能。

上面对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介绍的更多相关文章

  1. java并发编程(十五)----(线程池)java线程池简介

    好的软件设计不建议手动创建和销毁线程.线程的创建和销毁是非常耗 CPU 和内存的,因为这需要 JVM 和操作系统的参与.64位 JVM 默认线程栈是大小1 MB.这就是为什么说在请求频繁时为每个小的请 ...

  2. java并发编程(十)----JUC原子类介绍

    今天我们来看一下JUC包中的原子类,所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程),原子操作可以是 ...

  3. java并发编程(十五)内存可见两种方式 加锁和volatile

    1.volatile变量是一种稍弱的同步机制在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比synchronized关键字更轻量级的同步机制. ...

  4. java并发编程(十一)----(JUC原子类)基本类型介绍

    上一节我们说到了基本原子类的简单介绍,这一节我们先来看一下基本类型: AtomicInteger, AtomicLong, AtomicBoolean.AtomicInteger和AtomicLong ...

  5. java并发编程笔记(五)——线程安全策略

    java并发编程笔记(五)--线程安全策略 不可变得对象 不可变对象需要满足的条件 对象创建以后其状态就不能修改 对象所有的域都是final类型 对象是正确创建的(在对象创建期间,this引用没有逸出 ...

  6. Java并发编程二三事

    Java并发编程二三事 转自我的Github 近日重新翻了一下<Java Concurrency in Practice>故以此文记之. 我觉得Java的并发可以从下面三个点去理解: * ...

  7. 聊聊高并发(二十五)解析java.util.concurrent各个组件(七) 理解Semaphore

    前几篇分析了一下AQS的原理和实现.这篇拿Semaphore信号量做样例看看AQS实际是怎样使用的. Semaphore表示了一种能够同一时候有多个线程进入临界区的同步器,它维护了一个状态表示可用的票 ...

  8. 并发编程(十五)——定时器 ScheduledThreadPoolExecutor 实现原理与源码深度解析

    在上一篇线程池的文章<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中从ThreadPoolExecutor源码分析了其运行机制.限于篇幅,留下了Scheduled ...

  9. Java并发(二十):线程本地变量ThreadLocal

    ThreadLocal是一个本地线程副本变量工具类. 主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不同的 ...

随机推荐

  1. 数据结构与算法---树结构(Tree structure)

    为什么需要树这种数据结构 数组存储方式的分析 优点:通过下标方式访问元素,速度快.对于有序数组,还可使用二分查找提高检索速度. 缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低 ...

  2. XTOJ 1267:Highway(树的直径)***

    http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1267 题意:给出一棵树,每条树边有权值,现在要修建n-1条边,边的权值为边 ...

  3. 数字IC前后端设计中的时序收敛(一)前言

    本文转自:自己的微信公众号<数字集成电路设计及EDA教程> 里面主要讲解数字IC前端.后端.DFT.低功耗设计以及验证等相关知识,并且讲解了其中用到的各种EDA工具的教程. 为了纪念,同时 ...

  4. Java项目案例之--封装的实例

    Java项目案例之---封装的实例 有一个专业类,有一个专业对象,专业名称:计算机科学与技术,专业编号:J001,专业年限:4,对年限添加约束,如果输入小于0,则默认为0,否则显示输入的值 有一个学生 ...

  5. 微信小程序 键盘显示短信验证码

    1.场景描述: IOS系统 一些APP或者微信小程序在收到短信验证码的时候会在键盘上自动保存验证码信息,当用户点击的时候,会自动赋值到当前所点击的输入框中 2.案例: 2.实现: TIPS:这个功能是 ...

  6. android_alertDialog

    主文件 package cn.com.sxp;import android.app.Activity;import android.app.AlertDialog;import android.con ...

  7. 和朱晔一起复习Java并发(二):队列

    和朱晔一起复习Java并发(二):队列 老样子,我们还是从一些例子开始慢慢熟悉各种并发队列.以看小说看故事的心态来学习不会显得那么枯燥而且更容易记忆深刻. 阻塞队列的等待? 阻塞队列最适合做的事情就是 ...

  8. 人事管理系统为你解剖JSP

    人事管理系统为你解剖JSP 前言: 之前写过两篇学习JSP的博客,<Java匹马行天下之JavaWeb核心技术——JSP>https://www.cnblogs.com/zyx110/p/ ...

  9. Java-面向对象oop

    在提到面向对象的时候,大多数的书上面介绍的是简短的 类是对象的集合,对象是类的实例化.这样笼统的说法的确可以概括面向对象的思想,但却不能让一个刚入门的人理解到面向对象. 在这里先介绍一下类,当你在Ja ...

  10. vijos P1848 记数问题

    自答[119ms内存456.0 KiB] #include<iostream>using namespace std;int num = 0;void judge(int n, int x ...