ConcurrentLinkedQueue的offer方法

1、构造函数

public ConcurrentLinkedQueue() {
    head = tail = new Node<E>(null);
}

点击new Node(null)进入如下代码

Node(E item) {
   UNSAFE.putObject(this, itemOffset, item);
}

这里的itemOffset是item这个属性相对于Node对象地址的偏移量。
这个构造函数其实就是创建一个值为null的节点,并让head和tail指向该节点
这两个指针都是volatile的

private transient volatile Node<E> head;
private transient volatile Node<E> tail;

一张图总结:
在这里插入图片描述
注意:
1、Node类中只有next指针,说明这个队列是单项链表

2、offer方法

public boolean offer(E e) {
		//值不能为null
       checkNotNull(e);
       final Node<E> newNode = new Node<E>(e);

       for (Node<E> t = tail, p = t;;) {
           Node<E> q = p.next;
           if (q == null) {
               // p is last node
               if (p.casNext(null, newNode)) {
                   // Successful CAS is the linearization point
                   // for e to become an element of this queue,
                   // and for newNode to become "live".
                   if (p != t) // hop two nodes at a time
                       casTail(t, newNode);  // Failure is OK.
                   return true;
               }
               // Lost CAS race to another thread; re-read next
           }
           else if (p == q)
               // We have fallen off list.  If tail is unchanged, it
               // will also be off-list, in which case we need to
               // jump to head, from which all live nodes are always
               // reachable.  Else the new tail is a better bet.
               p = (t != (t = tail)) ? t : head;
           else
               // Check for tail updates after two hops.
               p = (p != t && t != (t = tail)) ? t : q;
       }
}

3、添加第一个元素

以offer(“张三”)为例
1) 执行到如下代码处

final Node<E> newNode = new Node<E>(e);

在这里插入图片描述
2)

Node<E> q = p.next;

在这里插入图片描述
3)下面这行代码的意思是,如果p节点的next指针指向null,则将其重新指向newNode

p.casNext(null, newNode)

点击casNext进入如下代码

boolean casNext(Node<E> cmp, Node<E> val) {
   return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}

在这里插入图片描述
注意:这里是通过CAS操作把新节点添加到链表中,同一时间只有一个线程可以执行成功。

4、添加第二个元素

以offer(“李四”)为例
1)

final Node<E> newNode = new Node<E>(e);

在这里插入图片描述
2)

Node<E> q = p.next;

在这里插入图片描述
3)下面这个代码是将p指向了q指针

else
    // Check for tail updates after two hops.
     p = (p != t && t != (t = tail)) ? t : q;

在这里插入图片描述
第一轮循环结束,进入第二轮循环
4)

Node<E> q = p.next;

在这里插入图片描述
5)

p.casNext(null, newNode)

在这里插入图片描述
6)

if (p != t) 
        casTail(t, newNode);

在这里插入图片描述

5、添加第三个元素

以offer(“王五”)为例
1)

 final Node<E> newNode = new Node<E>(e);

在这里插入图片描述
2)循环条件初始化

 for (Node<E> t = tail, p = t;;) 

在这里插入图片描述
3)

Node<E> q = p.next;

在这里插入图片描述
4)

p.casNext(null, newNode)

在这里插入图片描述

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值