Java之集合(十七)ConcurrentLinkedQueue
转载请注明源出处:http://www.cnblogs.com/lighten/p/7491057.html
1.前言
ConcurrentLinkedQueue是一个无界的线程安全队列,遵循FIFO先进先出的原则。头元素就是队列中存在最长时间的一个元素,即插入元素都是尾插入。检索是从头元素开始,不允许存在空元素。迭代器是弱一致性的,不会抛出并发异常。注意:size方法不是一个线性时间操作,这是由于队列的特点,需要遍历统计,如果遍历过程中有修改,就可能得到错误的结果(如果不是需要具体值,一般使用isEmpty来判断,比size>0快)。此外,bulk操作,即addAll,removeAll,retainAll,containsAll和equals,toArray这些方法不保证原子性。
2.ConcurrentLinkedQueue
2.1 数据结构
数据结构非常简单,就只有一个head和一个tail的Node类型头尾节点,所以其size方法是遍历出来的,由于没有加锁,所以该size实际上可能不正确。

Node节点也十分的简单,只有一个值和下一个节点的引用。不过其替换都是通过CAS操作完成的。

头尾结点初始化为一个值为null的结点。
2.2 基本操作
添加一个元素:

第一时间就将tail节点赋值给t,t就是当前时刻的一个快照。先从单线程开始理解,先插入一个元素1,这个时候q==null,设置p的next为元素1,注意此时tail节点并没有被改变。再插入一个元素2,由于tail没有改变,所以p不为null,p = q = 元素1进入下一个循环,元素1的后面节点为null,所以元素2被设置为元素1的next,此时p!=t,重置元素尾。由这个过程可以看出,tail并不是第一时间进行改变,而是要隔一个以上进行变化。多线程下就存在插队的情况了,被插队了还需要判断是否被插入了多个队,尾结点被改变了就被插入两个并改变了,就需要以最新的尾结点进行循环尝试插入,否则就选择后面一个节点。p==q的情况发生在poll操作的时候:假设队列中只有二个节点,但是在重新定义tail节点的时候被其它线程抢占了,此时head和tail都没有改变。A线程再插入一个元素,此时t=tail,p=tail,在q赋值的时候暂停了,这里要明白head与tail是相等的,是为null的结点。B线程执行poll操作,poll第一次头结点元素是null,不是我们需要的,再次循环,找到元素1。元素1更新头结点的时候,队列的head变成了元素2,但是head的next(null节点)变成了head自己。这个时候回到A线程,tail=head的,q=tail.next=tail=p,就是这样产生的p等于q。如果还没明白参考文章:这里。
取出一个元素:

这里在上面也描述了一些。poll设置头结点也是要跳过一个才会设置头结点。理解了这个,这段代码也就没什么了,也就是通过CAS进行保证线程安全。这里p==q的情况就更简单了,就是offer的情况,不过是同时有两个线程poll而已,B线程成功了,C线程失败了就会产生p==q的情况。
其它的方法就不再进行描述了。该集合使用的时候还是需要注意的,使用不当效率反而会下降。再给一篇参考文章:这里。
Java之集合(十七)ConcurrentLinkedQueue的更多相关文章
- 【Java】集合_学习笔记
一.集合 1.集合类也称容器类,主要负责保存.盛装其他数据. 2.集合可以保存数量不确定的数据,保存具有映射关系的数据(也称关联数组). 3.Java5后提供一些多线程安全的集合类,放在java.ut ...
- java的集合框架最全详解
java的集合框架最全详解(图) 前言:数据结构对程序设计有着深远的影响,在面向过程的C语言中,数据库结构用struct来描述,而在面向对象的编程中,数据结构是用类来描述的,并且包含有对该数据结构操作 ...
- 谈谈Java的集合组件
让我们一起谈谈Java的集合组件 我们在使用Java的时候,都会遇到并使用到Java的集合.在这里通过自己的理解和网上的资源对Java的集合方面的使用做一个简单的讲解和总结. Java主要分为3个集合 ...
- java.util 集合框架集合
java的集合框架为程序提供了一种处理对象组的标准方式.设计了一系列标准泛型接口: ⑴Collection ()接口,扩展了Iterable接口,位于集合层次结构的顶部,因此所有的集合都实现Colle ...
- Java基础——集合框架
Java的集合框架是Java中很重要的一环,Java平台提供了一个全新的集合框架.“集合框架”主要由一组用来操作对象的接口组成.不同接口描述一组不同数据类型.Java平台的完整集合框架如下图所示: 上 ...
- Java学习-集合(转)
在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的ArrayList. ...
- java的集合框架之一
java是一套很成熟的东西,很多商用的东西都喜欢用它,用的人多,稳定.不过一般也不怎么说起它,因为太常见了,私下里说,写java应用层得就像农民工,每一处都是搭积木,根据设计师的东西如何优雅地搭好积木 ...
- 浅谈Java的集合框架
浅谈Java的集合框架 一. 初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...
- Java之集合初探(一)
一.集合概述.区别 集合是一种容器,数组也是一种容器 在Java编程中,装各种各样的对象(引用类型)的叫做容器. 为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的 ...
随机推荐
- [GO]删除切片的某个值
func removePro(ddbenv []*model.EnvInfo, k int) []*model.EnvInfo { :]...) } for k, v := range ddbenv ...
- GitHub 安装配置
1:到 Github 注册 页面中注册,填写用户名.邮箱和密码 选择免费服务 步骤三可以根据自身喜好勾选或者直接跳过 2.1.2 创建远程仓库 创建完账号后,可以开始创建仓库 但是这里我们还没有验证邮 ...
- HDU 2138 How many prime numbers (判素数,米勒拉宾算法)
题意:给定一个数,判断是不是素数. 析:由于数太多,并且太大了,所以以前的方法都不适合,要用米勒拉宾算法. 代码如下: #include <iostream> #include <c ...
- springMVC学习(注解实现依赖注入)
原文:http://blog.csdn.net/mockingbirds/article/details/45399691 上一篇博客,学习了spring的依赖注入,即利用spring容器来为类中的属 ...
- Android中的Service 与 Thread 的区别[转]
很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下. 1). Thread:Thre ...
- Android APK反编译步骤
反编译步骤 1.通过Android Killer 打开apk,自动开始分析 2.分析结束后,在分析好的工程上右键->打开方式->打开文件位置 在文件夹ProjectSrc中有文 ...
- 软件工程网络15个人作业4(201521123010徐璐琳)——alpha阶段个人总结
一.个人总结 1. 总结自己的alpha 过程: 经过了两周的ALPHA阶段,在这之中学习到了很多,因为最开始其实是有抱着一种应付的.将就着的心理去做这个小程序,但是在完成项目的过程中,有老师和助教一 ...
- OpenGl 绘制一个立方体
OpenGl 绘制一个立方体 为了绘制六个正方形,我们为每个正方形指定四个顶点,最终我们需要指定6*4=24个顶点.但是我们知道,一个立方体其实总共只有八个顶点,要指定24次,就意味着每个顶点其实重复 ...
- java web 项目启动的根目录,以及项目启动后使用的端口具体是哪一个
1.今天启动项目发现一直找不到网页,原来是自己浏览器地址的根目录出现了问题,那么系统中的根目录(也就是项目名)到底是哪个,究竟以哪个为基准? 这里有一地方不能忽视:见图片 在普通的java web项目 ...
- Android 一个应用多个桌面图标
理解android.intent.action.MAIN 与 android.intent.category.LAUNCHER: 在Android 应用程序开发过程中,Activity入口会增加: a ...