高并发编程之ConcurrentLinkedQueue讲解

一、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 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	。
         */
        concurrentLinkedQueue.add(6);
        concurrentLinkedQueue.add(7);
        concurrentLinkedQueue.add(8);
        System.out.println("=====================");
        Iterator 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用来存放下一个节点,从而链接为一个单向无界列表。

你可能感兴趣的:(并发)