JDK8系列:阻塞队列 之 LinkedTransferQueue(无界阻塞队列)源码解析

1、LinkedTransferQueue 简介

是一个由链表结构构成的无界阻塞TransferQueue队列。相对于其他阻塞队列,多了  tryTransfer 和 transfer 方法。

LinkedTransferQueue是LinkedBlockingQueue、SynchronousQueue(公平模式)、ConcurrentLinkedQueue三者的集合体,它综合了这三者的方法,并且提供了更加高效的实现方式。

存储结构

LinkedTransferQueue使用了一个叫做dual data structure的数据结构,或者叫做dual queue,译为双重数据结构或者双重队列

双重队列是什么意思呢?

放取元素使用同一个队列,队列中的节点具有两种模式,一种是数据节点,一种是非数据节点。

放元素时先跟队列头节点对比,如果头节点是非数据节点,就让他们匹配,如果头节点是数据节点,就生成一个数据节点放在队列尾端(入队)。

取元素时也是先跟队列头节点对比,如果头节点是数据节点,就让他们匹配,如果头节点是非数据节点,就生成一个非数据节点放在队列尾端(入队)。

用图形来表示就是下面这样:

Dual Queue

不管是放元素还是取元素,都先跟头节点对比,如果二者模式不一样就匹配它们,如果二者模式一样,就入队。

同一时刻队列中只会存储一种类型的节点

通俗的讲就是:队列中的节点有两种状态;还未被消费(数据节点),或者已经被消费(非数据节点)。

put时,与头节点对比;如果是非数据节点(说明此节点已经被take消费了),那么就将其匹配(删除);如果是数据节点(说明前面还有节点未被消费),那么就将新节点放到tail

take时,与头节点对比;如果是数据节点(说明此节点)???

 

2、成员变量 和 构造方法

public class LinkedTransferQueue<E> extends AbstractQueue<E> implements TransferQueue<E>, java.io.Serializable{
    // 序列号
    private static final long serialVersionUID = -3223113410248163686L;

    // 是否是多核
    private static final boolean MP = Runtime.getRuntime().availableProcessors() > 1;

    // 自旋次数
    private static final int FRONT_SPINS   = 1 << 7;

    // 前驱节点正在处理,当前节点需要自旋的次数
    private static final int CHAINED_SPINS = FRONT_SPINS >>> 1;

    // 容忍清除节点失败次数的阈值
    static final int SWEEP_THRESHOLD = 32;

    // 头节点
    transient volatile Node head;
    // 尾节点
    private transient volatile Node tail;

    private transient volatile int sweepVotes;


    // 放取元素的几种方式:
    // 立即返回,用于非超时的poll()和tryTransfer()方法中
    private static final int NOW   = 0; // for untimed poll, tryTransfer
    // 异步,不会阻塞,用于放元素时,因为内部使用无界单链表存储元素,不会阻塞放元素的过程
    private static final int ASYNC = 1; // for offer, put, add
    // 同步,调用的时候如果没有匹配到会阻塞直到匹配到为止
    private static final int SYNC  = 2; // for transfer, take
    // 超时,用于有超时的poll()和tryTransfer()方法中
    private static final int TIMED = 3; // for timed poll, tryTransfer

    private static final sun.misc.Unsafe UNSAFE;
    private static final long headOffset;
    private static final long tailOffset;
    private static final long sweepVotesOffset;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> k = LinkedTransferQueue.class;
            headOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("head"));
            tailOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("tail"));
            sweepVotesOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("sweepVotes"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }
}

 

3、方法简介

3.1、主要构造方法

public LinkedTransferQueue() {}

public LinkedTransferQueue(Collection<? extends E> c) {
    this();
    addAll(c);
}

 

3.2、CAS 操作

// CAS methods for fields

// 1、CAS设置tail
private boolean casTail(Node cmp, Node val) {
    return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
}

// 2、CAS设置head
private boolean casHead(Node cmp, Node val) {
    return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
}

// 3、CAS设置sweepVotes
private boolean casSweepVotes(int cmp, int val) {
    return UNSAFE.compareAndSwapInt(this, sweepVotesOffset, cmp, val);
}

 

3.3、入队

xfer(E e, boolean haveData, int how, long nanos)的参数分别是:

(1)e表示元素;

(2)haveData表示是否是数据节点,

(3)how表示放取元素的方式,上面提到的四种,NOW、ASYNC、SYNC、TIMED;

(4)nanos表示超时时间;

add(E e)

public boolean add(E e) {
    xfer(e, true, ASYNC, 0);
    return true;
}

offer(E e)

public boolean offer(E e) {
    xfer(e, true, ASYNC, 0);
    return true;
}

offer(E e, long timeout, TimeUnit unit)  

public boolean offer(E e, long timeout, TimeUnit unit) {
    xfer(e, true, ASYNC, 0);
    return true;
}

 put(E e)

public void put(E e) {
    xfer(e, true, ASYNC, 0);
}

 

3.4、出队

remove(Object o)

public boolean remove(Object o) {
    return findAndRemove(o);
}

poll()

public E poll() {
    return xfer(null, false, NOW, 0);
}

poll(long timeout, TimeUnit unit) 

public E poll(long timeout, TimeUnit unit) throws InterruptedException {
    E e = xfer(null, false, TIMED, unit.toNanos(timeout));
    if (e != null || !Thread.interrupted())
        return e;
    throw new InterruptedException();
}

take()  

public E take() throws InterruptedException {
    E e = xfer(null, false, SYNC, 0);
    if (e != null)
        return e;
    Thread.interrupted();
    throw new InterruptedException();
}

 

3.5、移交元素的方法

请注意第二个参数,都是true,也就是这三个方法其实也是放元素的方法

 transfer(E e)

public void transfer(E e) throws InterruptedException {
    if (xfer(e, true, SYNC, 0) != null) {
        Thread.interrupted(); // failure possible only due to interrupt
        throw new InterruptedException();
    }
}

tryTransfer(E e) 

public boolean tryTransfer(E e) {
    return xfer(e, true, NOW, 0) == null;
}

tryTransfer(E e, long timeout, TimeUnit unit) 

public boolean tryTransfer(E e, long timeout, TimeUnit unit) throws InterruptedException {
    if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null)
        return true;
    if (!Thread.interrupted())
        return false;
    throw new InterruptedException();
}

 

3.6、核心方法 :

xfer(E e, boolean haveData, int how, long nanos) 

// haveData : put是true;  take是false
private E xfer(E e, boolean haveData, int how, long nanos) {
    // 不允许放入空元素
    if (haveData && (e == null))
        throw new NullPointerException();
    Node s = null;                        // the node to append, if needed

    retry:
    // 外层循环,自旋,失败就重试
    for (;;) {                            
  
        // 下面这个for循环用于控制匹配的过程
        // 同一时刻队列中只会存储一种类型的节点
        // 从头节点开始尝试匹配,如果头节点被其它线程先一步匹配了,就再尝试其下一个,直到匹配到为止,或者到队列中没有元素为止

        for (Node h = head, p = h; p != null;) { // 找到第一个匹配的节点
            boolean isData = p.isData;  //p节点的模式
            Object item = p.item;       //p节点的值
            // p没有被匹配到
            if (item != p && (item != null) == isData) { 
                // 如果两者模式一样,则不能匹配,跳出循环后尝试入队
                // isData=haveData=true,put和data;   isData=haveData=false,take和非data
                if (isData == haveData)   
                    break;

                // 如果两者模式不一样,则尝试匹配
                // 把p的值设置为e(如果是取元素则e是null,如果是放元素则e是元素值)
                if (p.casItem(item, e)) { 
                    // 匹配成功
                    // for里面的逻辑比较复杂,用于控制多线程同时放取元素时出现竞争的情况的
                    for (Node q = p; q != h;) {
                        // 进入到这里可能是头节点已经被匹配,然后p会变成h的下一个节点 
                        Node n = q.next;  
                        // 如果head还没变,就把它更新成新的节点
                        // 并把它删除(forgetNext()会把它的next设为自己,也就是从单链表中删除了)
                        // 这时为什么要把head设为n呢?因为到这里了,肯定head本身已经被匹配掉了
                        // 而上面的p.casItem()又成功了,说明p也被当前这个元素给匹配掉了
                        // 所以需要把它们俩都出队列,让其它线程可以从真正的头开始,不用重复检查了
                        if (head == h && casHead(h, n == null ? q : n)) {
                            h.forgetNext();
                            break;  //跳出循环
                        }                 // advance and retry

                        // 如果新的头节点为空,或者其next为空,或者其next未匹配,就重试
                        if ((h = head)   == null ||
                                (q = h.next) == null || !q.isMatched())
                            break;        // unless slack < 2
                    }
                    // 唤醒p中等待的线程
                    LockSupport.unpark(p.waiter);
                    // 并返回匹配到的元素
                    return LinkedTransferQueue.<E>cast(item);
                }
            }

            // p已经被匹配了或者尝试匹配的时候失败了
            // 也就是其它线程先一步匹配了p
            // 这时候又分两种情况,p的next还没来得及修改,p的next指向了自己
            // 如果p的next已经指向了自己,就重新取head重试,否则就取其next重试
            Node n = p.next;
            p = (p != n) ? n : (h = head); // Use head if p offlist
        }

        // 到这里肯定是队列中存储的节点类型和自己一样
        // 或者队列中没有元素了
        // 就入队(不管放元素还是取元素都得入队)
        // 入队又分成四种情况:
        // NOW,立即返回,没有匹配到立即返回,不做入队操作
        // ASYNC,异步,元素入队但当前线程不会阻塞(相当于无界LinkedBlockingQueue的元素入队)
        // SYNC,同步,元素入队后当前线程阻塞,等待被匹配到
        // TIMED,有超时,元素入队后等待一段时间被匹配,时间到了还没匹配到就返回元素本身

        // 如果 不是立即返回
        if (how != NOW) {                 // No matches available
            //  新建s节点
            if (s == null)
                s = new Node(e, haveData);
            // 尝试入队
            Node pred = tryAppend(s, haveData);
            // 入队失败,重试
            if (pred == null)
                continue retry;           // lost race vs opposite mode

            // 如果不是异步(同步或者有超时)
            // 就等待被匹配
            if (how != ASYNC)
                return awaitMatch(s, pred, e, (how == TIMED), nanos);
        }
        return e; // not waiting
    }
}

tryAppend(Node s, boolean haveData) 

private Node tryAppend(Node s, boolean haveData) {
    // 从tail开始遍历,把s放到链表尾端
    for (Node t = tail, p = t;;) {        // move p to last node and append
        Node n, u;                        // temps for reads of next & tail
        //  如果首尾都是null,说明链表中还没有元素
        if (p == null && (p = head) == null) {
            // 就让首节点指向s
            // 注意,这里插入第一个元素的时候tail指针并没有指向s
            if (casHead(null, s))
                return s;                 // initialize
        }
        
        // 如果p无法处理,则返回null
        // 这里无法处理的意思是,p和s节点的类型不一样,不允许s入队
        // 比如,其它线程先入队了一个数据节点,这时候要入队一个非数据节点,就不允许,
        // 队列中所有的元素都要保证是同一种类型的节点
        // 返回null后外面的方法会重新尝试匹配重新入队等
        else if (p.cannotPrecede(haveData))
            return null;                  // lost race vs opposite mode

        // 如果p的next不为空,说明不是最后一个节点
        // 则让p重新指向最后一个节点
        else if ((n = p.next) != null)    // not last; keep traversing
            p = p != t && t != (u = tail) ? (t = u) : // stale tail
                        (p != n) ? n : null;      // restart if off list

        // 如果CAS更新s为p的next失败
        // 则说明有其它线程先一步更新到p的next了
        // 就让p指向p的next,重新尝试让s入队
        else if (!p.casNext(null, s))
            p = p.next;                   // re-read on CAS failure

        // 到这里说明s成功入队了
        // 如果p不等于t,就更新tail指针
        // 还记得上面插入第一个元素时tail指针并没有指向新元素吗?
        // 这里就是用来更新tail指针的
        else {
            if (p != t) {                 // update if slack now >= 2
                while ((tail != t || !casTail(t, s)) &&
                            (t = tail)   != null &&
                            (s = t.next) != null && // advance and retry
                            (s = s.next) != null && s != t);
            }
            return p;   // 返回p,即s的前一个元素
        }
    }
}

awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) 

private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) {
    // 如果是有超时的,计算其超时时间
    final long deadline = timed ? System.nanoTime() + nanos : 0L;
    // 当前线程
    Thread w = Thread.currentThread();
    // 自旋次数
    int spins = -1; // initialized after first item and cancel checks
    //  随机数,随机让一些自旋的线程让出CPU
    ThreadLocalRandom randomYields = null; // bound if needed

    for (;;) {
        Object item = s.item;
        // 如果s元素的值不等于e,说明它被匹配到了
        if (item != e) {                  // matched
            // assert item != s;
            // 把s的item更新为s本身
            // 并把s中的waiter置为空
            s.forgetContents();           // avoid garbage
            // 返回匹配到的元素
            return LinkedTransferQueue.<E>cast(item);
        }

        // 如果当前线程中断了,或者有超时的到期了
        // 就更新s的元素值指向s本身
        if ((w.isInterrupted() || (timed && nanos <= 0)) &&
                s.casItem(e, s)) {        // cancel
            // 尝试解除s与其前一个节点的关系
            // 也就是删除s节点
            unsplice(pred, s);
            // 返回元素的值本身,说明没匹配到
            return e;
        }

        // 如果自旋次数小于0,就计算自旋次数
        if (spins < 0) {                  // establish spins at/near front
            // spinsFor()计算自旋次数
            // 如果前面有节点未被匹配就返回0
            // 如果前面有节点且正在匹配中就返回一定的次数,等待
            if ((spins = spinsFor(pred, s.isData)) > 0)
                // 初始化随机数
                randomYields = ThreadLocalRandom.current();
        }

        // 还有自旋次数就减1,并随机让出CPU
        else if (spins > 0) {             // spin
            --spins;
            if (randomYields.nextInt(CHAINED_SPINS) == 0)
                Thread.yield();           // occasionally yield
        }

        // 更新s的waiter为当前线程
        else if (s.waiter == null) {
            s.waiter = w;                 // request unpark then recheck
        }

        // 如果有超时,计算超时时间,并阻塞一定时间
        else if (timed) {
            nanos = deadline - System.nanoTime();
            if (nanos > 0L)
                LockSupport.parkNanos(this, nanos);
        }

        // 不是超时的,直接阻塞,等待被唤醒
        // 唤醒后进入下一次循环,走第一个if的逻辑就返回匹配的元素了
        else {
            LockSupport.park(this);
        }
    }
}

这三个方法里的内容特别复杂,很大一部分代码都是在控制线程安全,各种CAS,我们这里简单描述一下大致的逻辑:

(1)来了一个元素,我们先查看队列头的节点,是否与这个元素的模式一样;

(2)如果模式不一样,就尝试让他们匹配,如果头节点被别的线程先匹配走了,就尝试与头节点的下一个节点匹配,如此一直往后,直到匹配到或到链表尾为止;

(3)如果模式一样,或者到链表尾了,就尝试入队;

(4)入队的时候有可能链表尾修改了,那就尾指针后移,再重新尝试入队,依此往复;

(5)入队成功了,就自旋或阻塞,阻塞了就等待被其它线程匹配到并唤醒;

(6)唤醒之后进入下一次循环就匹配到元素了,返回匹配到的元素;

(7)是否需要入队及阻塞有四种情况:

           a)NOW,立即返回,没有匹配到立即返回,不做入队操作 对应的方法有:poll()、tryTransfer(e)

          b)ASYNC,异步,元素入队但当前线程不会阻塞(相当于无界LinkedBlockingQueue的元素入队) 对应的方法有:add(e)、offer(e)、put(e)、offer(e, timeout, unit)

          c)SYNC,同步,元素入队后当前线程阻塞,等待被匹配到 对应的方法有:take()、transfer(e)

          d)TIMED,有超时,元素入队后等待一段时间被匹配,时间到了还没匹配到就返回元素本身 对应的方法有:poll(timeout, unit)、tryTransfer(e, timeout, unit)

 

总结

(1)LinkedTransferQueue可以看作LinkedBlockingQueue、SynchronousQueue(公平模式)、ConcurrentLinkedQueue三者的集合体;

(2)LinkedTransferQueue的实现方式是使用一种叫做双重队列的数据结构;

(3)不管是取元素还是放元素都会入队;

(4)先尝试跟头节点比较,如果二者模式不一样,就匹配它们,组成CP,然后返回对方的值;

(5)如果二者模式一样,就入队,并自旋或阻塞等待被唤醒;

(6)至于是否入队及阻塞有四种模式,NOW、ASYNC、SYNC、TIMED;

(7)LinkedTransferQueue全程都没有使用synchronized、重入锁等比较重的锁,基本是通过 自旋+CAS 实现;

(8)对于入队之后,先自旋一定次数后再调用LockSupport.park()或LockSupport.parkNanos阻塞;

 

彩蛋

LinkedTransferQueue与SynchronousQueue(公平模式)有什么异同呢?

(1)在java8中两者的实现方式基本一致,都是使用的双重队列;

(2)前者完全实现了后者,但比后者更灵活;

(3)后者不管放元素还是取元素,如果没有可匹配的元素,所在的线程都会阻塞;

(4)前者可以自己控制放元素是否需要阻塞线程,比如使用四个添加元素的方法就不会阻塞线程,只入队元素,使用transfer()会阻塞线程;

(5)取元素两者基本一样,都会阻塞等待有新的元素进入被匹配到;

 

3.7、其他方法(从这里到后面的可以不看!!!)

cast(Object item)

// 类型转换,将object转换成 queue 中节点的类型
static <E> E cast(Object item) {
    // assert item == null || item.getClass() != Node.class;
    return (E) item;
}

spinsFor 

// 计算自旋次数
private static int spinsFor(Node pred, boolean haveData) {
    if (MP && pred != null) {
        if (pred.isData != haveData)      // phase change
        return FRONT_SPINS + CHAINED_SPINS;
        if (pred.isMatched())             // probably at front
            return FRONT_SPINS;
        if (pred.waiter == null)          // pred apparently spinning
            return CHAINED_SPINS;
    }
    return 0;
}

succ(Node p)  

// 返回p的后继节点,或者head(如果p.next=p)
final Node succ(Node p) {
    Node next = p.next;
    return (p == next) ? head : next;
}

firstOfMode(boolean isData) 

// 返回给定模式的第一个不匹配节点,如果没有,则返回null
// 被isEmpty()、hasWaitingConsumer() 方法调用
private Node firstOfMode(boolean isData) {
    for (Node p = head; p != null; p = succ(p)) {
        if (!p.isMatched())
            return (p.isData == isData) ? p : null;
    }
    return null;
}

firstDataNode() 

final Node firstDataNode() {
    for (Node p = head; p != null;) {
        Object item = p.item;
        if (p.isData) {
            if (item != null && item != p)
                return p;
        }
        else if (item == null)
            break;
        if (p == (p = p.next))
            p = head;
    }
    return null;
}

firstDataItem() 

private E firstDataItem() {
    for (Node p = head; p != null; p = succ(p)) {
        Object item = p.item;
        if (p.isData) {
            if (item != null && item != p)
                return LinkedTransferQueue.<E>cast(item);
        }
        else if (item == null)
            return null;
    }
    return null;
}

 peek()  

public E peek() {
    return firstDataItem();
}

 countOfMode(boolean data) 

private int countOfMode(boolean data) {
    int count = 0;
    for (Node p = head; p != null; ) {
        if (!p.isMatched()) {
            if (p.isData != data)
                return 0;
            if (++count == Integer.MAX_VALUE) // saturated
                break;
        }
        Node n = p.next;
        if (n != p)
            p = n;
        else {
            count = 0;
            p = head;
        }
    }
    return count;
}

iterator() 

public Iterator<E> iterator() {
    return new Itr();
}

spliterator() 

public Spliterator<E> spliterator() {
    return new LTQSpliterator<E>(this);
}

unsplice(Node pred, Node s) 

final void unsplice(Node pred, Node s) {
    s.forgetContents(); // forget unneeded fields

    if (pred != null && pred != s && pred.next == s) {
        Node n = s.next;
        if (n == null ||
                (n != s && pred.casNext(s, n) && pred.isMatched())) {
            for (;;) {               // check if at, or could be, head
                Node h = head;
                if (h == pred || h == s || h == null)
                    return;          // at head or list empty
                if (!h.isMatched())
                    break;
                Node hn = h.next;
                if (hn == null)
                    return;          // now empty
                if (hn != h && casHead(h, hn))
                    h.forgetNext();  // advance head
            }
            if (pred.next != pred && s.next != s) { // recheck if offlist
                for (;;) {           // sweep now if enough votes
                    int v = sweepVotes;
                    if (v < SWEEP_THRESHOLD) {
                        if (casSweepVotes(v, v + 1))
                            break;
                    }
                    else if (casSweepVotes(v, 0)) {
                        sweep();
                        break;
                    }
                }
            }
        }
    }
}

sweep() 

private void sweep() {
    for (Node p = head, s, n; p != null && (s = p.next) != null; ) {
        if (!s.isMatched())
            // Unmatched nodes are never self-linked
            p = s;
        else if ((n = s.next) == null) // trailing node is pinned
            break;
        else if (s == n)    // stale
            // No need to also check for p == s, since that implies s == n
            p = head;
        else
            p.casNext(s, n);
    }
}

findAndRemove(Object e)  

/**
* Main implementation of remove(Object)
*/
private boolean findAndRemove(Object e) {
    if (e != null) {
        for (Node pred = null, p = head; p != null; ) {
            Object item = p.item;
            if (p.isData) {
                if (item != null && item != p && e.equals(item) &&
                            p.tryMatchData()) {
                    unsplice(pred, p);
                    return true;
                }
            }
            else if (item == null)
                break;
            pred = p;
            if ((p = p.next) == pred) { // stale
                pred = null;
                p = head;
            }
        }
    }
    return false;
}

drainTo(Collection<? super E> c) 

public int drainTo(Collection<? super E> c) {
    if (c == null)
        throw new NullPointerException();
    if (c == this)
        throw new IllegalArgumentException();
    int n = 0;
    for (E e; (e = poll()) != null;) {
        c.add(e);
        ++n;
    }
    return n;
}

drainTo(Collection<? super E> c, int maxElements) 

public int drainTo(Collection<? super E> c, int maxElements) {
    if (c == null)
        throw new NullPointerException();
    if (c == this)
        throw new IllegalArgumentException();
    int n = 0;
    for (E e; n < maxElements && (e = poll()) != null;) {
        c.add(e);
        ++n;
    }
    return n;
}

isEmpty() 

public boolean isEmpty() {
    for (Node p = head; p != null; p = succ(p)) {
        if (!p.isMatched())
            return !p.isData;
    }
    return true;
}

hasWaitingConsumer() 

public boolean hasWaitingConsumer() {
    return firstOfMode(false) != null;
}

size() 

public int size() {
    return countOfMode(true);
}

getWaitingConsumerCount() 

public int getWaitingConsumerCount() {
    return countOfMode(false);
}

contains(Object o) 

public boolean contains(Object o) {
    if (o == null) 
        return false;
    for (Node p = head; p != null; p = succ(p)) {
        Object item = p.item;
        if (p.isData) {
            if (item != null && item != p && o.equals(item))
                return true;
        }
        else if (item == null)
            break;
    }
    return false;
}

remainingCapacity() 

public int remainingCapacity() {
    return Integer.MAX_VALUE;
}

 

4、内部类

4.1、Node 类

static final class Node {
    final boolean isData;   // 表示存放数据还是获取数据
    volatile Object item;   // 存放数据是item有值
    volatile Node next;     // next节点
    volatile Thread waiter; // 等待线程,不等时为null

    // CAS methods for fields
    final boolean casNext(Node cmp, Node val) {
        return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
    }

    final boolean casItem(Object cmp, Object val) {
        // assert cmp == null || cmp.getClass() != Node.class;
        return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
    }

        /**
         * Constructs a new node.  Uses relaxed write because item can
         * only be seen after publication via casNext.
         */
    Node(Object item, boolean isData) {
        UNSAFE.putObject(this, itemOffset, item); // relaxed write
        this.isData = isData;
    }

        /**
         * Links node to itself to avoid garbage retention.  Called
         * only after CASing head field, so uses relaxed write.
         */
    final void forgetNext() {
        UNSAFE.putObject(this, nextOffset, this);
    }

    final void forgetContents() {
        UNSAFE.putObject(this, itemOffset, this);
        UNSAFE.putObject(this, waiterOffset, null);
    }

    final boolean isMatched() {
        Object x = item;
        return (x == this) || ((x == null) == isData);
    }

    final boolean isUnmatchedRequest() {
        return !isData && item == null;
    }

    final boolean cannotPrecede(boolean haveData) {
        boolean d = isData;
        Object x;
        return d != haveData && (x = item) != this && (x != null) == d;
    }

    final boolean tryMatchData() {
        // assert isData;
        Object x = item;
        if (x != null && x != this && casItem(x, null)) {
            LockSupport.unpark(waiter);
            return true;
        }
        return false;
    }

    private static final long serialVersionUID = -3375979862319811754L;

    // Unsafe mechanics
    private static final sun.misc.Unsafe UNSAFE;
    private static final long itemOffset;
    private static final long nextOffset;
    private static final long waiterOffset;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> k = Node.class;
            itemOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("item"));
            nextOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("next"));
            waiterOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("waiter"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }
}

 

4.2、Itr 类

4.3、LTQSpliterator 类

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值