看ConcurrentLinkedQueue这个名字,应该叫并发链表队列哈。html
ConcurrentLinkedQueue是一个基于连接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当咱们添加一个元素的时候,它会添加到队列的尾部,当咱们获取一个元素时,它会返回队列头部的元素。算法
ConcurrentLinkedQueue由head节点和tair节点组成,每一个节点(Node)由节点元素(item)和指向下一个节点的引用(next)组成,节点与节点之间就是经过这个next关联起来,从而组成一张链表结构的队列。默认状况下head节点存储的元素为空,tair节点等于head节点。安全
当许多线程共享对公共集合的访问权限时,ConcurrentLinkedQueue是一个合适的选择。与大多数其余并发集合实现同样,此类不容许使用null元素。多线程
该实现采用有效的非阻塞算法,该算法基于Maged M.Michael和Michael L.Scott提出的 Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms 中描述的算法。并发
迭代器是弱一致的,在迭代器建立时或以后的某个时刻返回反映队列状态的元素。它们不会抛出ConcurrentModificationException,而且可能与其余操做同时进行。异步
经常使用的并发队列有阻塞队列和非阻塞队列,前者使用锁实现,后者则使用CAS非阻塞算法实现,使用非阻塞队列通常性能比较好。性能
下面看看这个类的构造方法:this
方法的实现:线程
这里要先说一下链表结构实现的两个关键字段 head与tail,是用private transient volatile修饰:3d
能够看到这两个值是 Node,这个类的实现也比较关键。这里有两个属性E item,和Node<E> next,对值得的操做用了sun.misc.Unsafe UNSAFE里的方法实现。Node分别用来存在列表的首尾节点,其中head节点存放链表第一个item为null的节点,tail则并非总指向最后一个节点。Node节点内部则维护一个变量item用来存放节点的值,next用来存放下一个节点,从而连接为一个单向无界列表。
而后就是具体应用到相应的队列的方法里,好比offer方法的实现,将指定元素插入此队列的尾部。第一是定位出尾节点,第二是使用CAS算法能将入队节点设置成尾节点的next节点,如不成功则重试:
tail节点并不老是尾节点,因此每次入队都必须先经过tail节点来找到尾节点,尾节点可能就是tail节点,也多是tail节点的next节点。代码中循环体中的第一个if就是判断tail是否有next节点,有则表示next节点多是尾节点。
而后还有poll方法的实现,检索并删除此队列的头部,若是此队列为空,则返回null。并非每次出队时都更新head节点,当head节点里有元素时,直接弹出head节点里的元素,而不会更新head节点。只有当head节点里没有元素时,出队操做才会更新head节点:
首先获取头节点的元素,而后判断头节点元素是否为空,若是为空,表示另一个线程已经进行了一次出队操做将该节点的元素取走,若是不为空,则使用CAS的方式将头节点的引用设置成null,若是CAS成功,则直接返回头节点的元素,若是不成功,表示另一个线程已经进行了一次出队操做更新了head节点,致使元素发生了变化,须要从新获取头节点。
peek()方法的实现,检索但不移除此队列的头部,若是此队列为空,则返回null。
这里size()方法的实现,返回此队列中的元素数。与大多数集合不一样,size方法不是constant-time操做。因为这些队列的异步性质,肯定元素的当前数量须要遍历元素,所以若是在遍历期间修改此集合,则可能会报告不许确的结果。
还有remove方法的实现,若是队列里面存在该元素则删除给元素,若是存在多个则删除第一个,并返回true,否者返回false
发现一篇Importnew写的不错的博文:http://www.importnew.com/25668.html 对各类状况还画了图
有什么讨论的内容,能够加我公众号: