集合---非阻塞队列

队列概念

   Queue接口与List、Set为同级别,都为Collection接口子接口。除了拥有 Collection 接口基本操作外,队列还提供其他的插入、提取和检查操作。每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null 或 false,具体取决于操作)。插入操作的后一种形式是用于专门为有容量限制的 Queue 实现设计的;在大多数实现中,插入操作不会失败。

非阻塞队列:

ConcurrentLinkedQueue

    传统的Queue在面对多线程情况下,是无法达到线程安全的,解决该问题的方法有几种,加锁Synchronized可以解决,但是效率比较低,这里我们使用ConcurrentLinkedQueue来解决。

1.字段

    头节点和尾节点

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

节点:

private static class Node<E> {
    volatile E item;
    volatile Node<E> next;
...
}

该内容比较简单,重点是在入队和出队操作上面

2.入队列

    将新节点,防止到队列尾部,将tail指针更新到队列尾部,注意在多线程情况下,普通的入队,可能就会出现插队情况。

    由于高并发,所以head节点和tail节点并不是十分的精确,所以tail可能指向的是倒数第二个节点。

    多线程操作,没有上锁,注意中间随时都有被挂起的可能!

public boolean offer(E e) {
    checkNotNull(e);
    final Node<E> newNode = new Node<E>(e);    //将值包装成为一个新的节点

    for (Node<E> t = tail, p = t;;) {    //cas操作
        Node<E> q = p.next;
        if (q == null) { //判断P是tail节点
            if (p.casNext(null, newNode)) { //cas,期待值是null,更新值是newNode
                if (p != t)     //首次添加,不跟新,所以tail可能并不是最后的节点
                    casTail(t, newNode);  // 更新tail
                return true;
            }
            // Lost CAS race to another thread; re-read next
        }
        else if (p == q)
            p = (t != (t = tail)) ? t : head;
        else    //向队尾移动
            p = (p != t && t != (t = tail)) ? t : q;
    }
}

3.出队列

public E poll() {
    restartFromHead:
    for (;;) {
        for (Node<E> h = head, p = h, q;;) {
            //获取头节点的值
            E item = p.item;
            //cas操作将 头节点值设置为Null
            if (item != null && p.casItem(item, null)) {
                if (p != h) // hop two nodes at a time
                    updateHead(h, ((q = p.next) != null) ? q : p);
                return item;
            }
            else if ((q = p.next) == null) {
                updateHead(h, p);
                return null;
            }
            else if (p == q)
                continue restartFromHead;
            else
                p = q;
        }
    }
}

4.size()

public int size() {
    int count = 0;
    for (Node<E> p = first(); p != null; p = succ(p))
        if (p.item != null)
            if (++count == Integer.MAX_VALUE)
                break;
    return count;
}

succ()

final Node<E> succ(Node<E> p) {
    Node<E> next = p.next;
    return (p == next) ? head : next;
}

5.remove()

public boolean remove(Object o) {
    if (o != null) {
        Node<E> next, pred = null;
        for (Node<E> p = first(); p != null; pred = p, p = next) {
            boolean removed = false;
            E item = p.item;
            if (item != null) {
                if (!o.equals(item)) {
                    next = succ(p);
                    continue;
                }
                removed = p.casItem(item, null);
            }

            next = succ(p);
            if (pred != null && next != null) // unlink
                pred.casNext(p, next);
            if (removed)
                return true;
        }
    }
    return false;
}

 

 

参考:https://www.jianshu.com/p/231caf90f30b

          https://www.jianshu.com/p/1ed2c932d97b(概念)

         https://blog.csdn.net/qq_38293564/article/details/80798310

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值