一、ConcurrentLinkedQueue介绍
一个基于链接节点的无界线程安全队列。此队列按照 FIFO(先进先出)原则对元素进行排序。队列的头部 是队列中时间最长的元素,队列的尾部 是队列中时间最短的元素。当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法来实现,该算法在Michael & Scott算法上进行了一些修改, Michael & Scott算法的详细信息可以参见http://www.cs.rochester.edu/u/michael/PODC96.html。
二、ConcurrentLinkedQueue常用方法介绍
1、add(E e) :将指定元素插入此队列的尾部,返回值为Boolean。
2、contains(Object o) :如果此队列包含指定元素,则返回 true。
3、isEmpty() :如果此队列不包含任何元素,则返回 true。
4、iterator() :返回在此队列元素上以恰当顺序进行迭代的迭代器,返回值为 Iterator。
5、offer(E e) :将指定元素插入此队列的尾部,返回值为 boolean。
6、peek() :获取但不移除此队列的头;如果此队列为空,则返回 null。
7、poll() :获取并移除此队列的头,如果此队列为空,则返回 null。
8、remove(Object o) :从队列中移除指定元素的单个实例(如果存在),返回值为 boolean。
9、size():返回此队列中的元素数量。
10、toArray() :返回以恰当顺序包含此队列所有元素的数组。
三、Java代码示例
package chapter3.concurrentlinkedqueue;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* @author czd
*/
public class ConcurrentLinkedQueueTest {
public static void main(String[] args) {
/**
* 构造方法摘要
* ConcurrentLinkedQueue():
* 创建一个最初为空的 ConcurrentLinkedQueue
*/
ConcurrentLinkedQueue<Integer> concurrentLinkedQueue = new ConcurrentLinkedQueue();
/**
* 1、add(E e) :将指定元素插入此队列的尾部,返回值为Boolean。
*/
Boolean addBoolean = concurrentLinkedQueue.add(5);
System.out.println("是否添加到队列尾部成功: " + addBoolean);
/**
* 2、contains(Object o) :如果此队列包含指定元素,则返回 true。
*/
Boolean containsBoolean = concurrentLinkedQueue.contains(5);
System.out.println("是否包含5:" + containsBoolean);
/**
* 3、isEmpty() :如果此队列不包含任何元素,则返回 true
*/
Boolean isEmptyBoolean = concurrentLinkedQueue.isEmpty();
System.out.println("concurrentLinkedQueue是否为空:" + isEmptyBoolean);
/**
* 4、iterator() :返回在此队列元素上以恰当顺序进行迭代的迭代器,返回值为 Iterator<E> 。
*/
concurrentLinkedQueue.add(6);
concurrentLinkedQueue.add(7);
concurrentLinkedQueue.add(8);
System.out.println("=====================");
Iterator<Integer> iterator = concurrentLinkedQueue.iterator();
while (iterator.hasNext()){
System.out.println("iterator的结果:" + iterator.next());
}
/**
* 5、ffer(E e) :将指定元素插入此队列的尾部,返回值为boolean。
*/
Boolean offerBoolean = concurrentLinkedQueue.offer(9);
System.out.println("是否插入队列尾部成功:" + offerBoolean);
/**
* 6、peek() :获取但不移除此队列的头;如果此队列为空,则返回 null。
*/
Integer peekResult = concurrentLinkedQueue.peek();
System.out.println("队列的第一个信息:" + peekResult);
/**
* 7、poll() :获取并移除此队列的头,如果此队列为空,则返回 null。
*/
Integer pollResult = concurrentLinkedQueue.poll();
System.out.println("队列的第一个信息:" + pollResult);
/**
* 8、remove(Object o) :从队列中移除指定元素的单个实例(如果存在),返回值为Boolean。
*/
Boolean removeBoolean = concurrentLinkedQueue.remove(9);
System.out.println("是否移除9成功?" + removeBoolean);
/**
* 9、size():返回此队列中的元素数量
*/
Integer size = concurrentLinkedQueue.size();
System.out.println("队列的元素数量:" + size);
}
}
四、总结
1、ConcurrentLinkedQueue使用CAS非阻塞算法实现使用CAS解决了当前节点与next节点之间的安全链接和对当前节点值的赋值。由于使用CAS没有使用锁,所以获取size的时候有可能进行offer,poll或者remove操作,导致获取的元素个数不精确,所以在并发情况下size函数不是很有用。另外第一次peek或者first时候会把head指向第一个真正的队列元素。
2、ConcurrentLinkedQueue中有两个volatile类型的Node节点分别用来存在列表的首尾节点,其中head节点存放链表第一个item为null的节点,tail则并不是总指向最后一个节点。Node节点内部则维护一个变量item用来存放节点的值,next用来存放下一个节点,从而链接为一个单向无界列表。