简单实现BlockingQueue,BlockingQueue源码详解

目录

一、构造方法介绍

二、put方法

1.await方法

2.signal方法

三、take方法        

四、代码

1.ArrayBlockingQueue

2.ReentrantLock 

3.AbstractQueuedSynchronizer

总结



前言

关于AbstractOwnableSynchronizer的讲解可以看我的这篇文章,ReentrantLock源码介绍

这里主要介绍ArrayBlockingQueue,具体的解析可以看最后附上的代码,上面有详细的注释。

目录结构:


一、构造方法介绍

通过构造方法创建ArrayBlockingQueue。

  1. capcity是数组的大小。当数组 满了/空 了后就不允许再继续 放入/获取 元素了,尝试放入或者获取的线程就应该进入等待状态,直到数组的元素被 消耗/添加 了
  2. 创建了items数组,这个数组用于存放添加到queue的元素。
  3. 创建了ReentrantLock锁,只有获取到了锁才能进行 存取 操作。ReentrantLock里面有一个CLH队列,没有获取到锁的线程就会在这个线程里面等待
  4. 创建了notFull条件队列。当尝试存放元素到items中时,如果线程获得了锁,但是items数组满了的时候,就会进入notFull的条件队列里面进行等待。
  5. 创建了notEmpty条件队列。当尝试从items中取得元素时,如果线程获得了锁,但是items为空,就会进入notEmpty队列中进行等待。
  6. 在进入条件队列中进行等待的时候,会释放锁并且让出CPU的使用权。

二、put方法

        当调用put方法时,线程A调用lock.lockInterruptibly()方法进行加锁,加锁后判断items是否满了,如果满了就调用await方法notFull条件队列里面进行等待。在等待之前通过fullRelease方法释放锁,并通过park方法释放CPU,然后线程A就进入了睡眠状态。直到take方法被调用,消耗了元素后会调用signal方法,该方法会将线程A从条件等待队列放入CLH队列。当占有锁的线程释放锁的时候,线程A被唤醒,并且尝试获取锁。获取到锁后会再次判断items队列是否满了。如果没满,调用enq方法将元素放进到items中 并且 ,最后再把锁释放掉。

        具体的逻辑解释看最底下的代码。

1.await方法

        调用put方法时,如果items满了,就会进入await方法。await方法会先将当前线程封装为一个node对象,放进条件队列里面。再把同步器的thread设为空,State设为0,以此来释放锁。释放锁以后进入一个循环,只有当前节点转移到CLH队列时才会出这个循环。如果没在队列中就一直park住等待。当在CLH队列出了循环的时候,该线程会尝试获取锁,如果没获取成功则会再次park住。获取锁成功以后则会根据该线程是被unpark唤醒还是打断唤醒进行相关的操作。

2.signal方法

        当调用enq方法把对象放进items数组后,就会执行signal操作。如果条件队列里面有线程在等待,则会执行doSignal方法。doSignal方法会将每个对象从条件队列中移除,并通过transferForSignal方法放入CLH队列中。

三、take方法        

        take方法的逻辑和put方法相似,不同之处在于take方法时判断items数组是否为空。如果为空的话就进入条件队列里去等待。

四、代码

1.ArrayBlockingQueue

package tools.myBlockingQueue;

import java.util.Objects;


/**
 * @Auther: duanYL
 * @Date: 2023/10/18/10:31
 * @Description:
 */
public class ArrayBlockingQueue<E> {

    final Object[] items;
    int takeIndex;
    int putIndex;
    int count;

    final ReentrantLock lock;
    private final Condition notEmpty;
    private final Condition notFull;

    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull = lock.newCondition();
    }

    public void put(E e) throws InterruptedException {
        Objects.requireNonNull(e);  //出队入队共用一把锁,所以在同一时刻,只能有一个线程进行操作
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();   //禁止在获取锁的时候打断
        try {  //这里加try,finally保证出现异常时,最后也能释放锁,避免堵塞住
            while (items.length == count) {
                notFull.await();
            }
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 这是个循环队列,传统的循环队列判满是通过取模实现的
     * 即 (putIndex+1)%items.size()==takeIndex
     * 而这里使用了一个count参数来进行队列判断,这样的好处是不会浪费一个空间
     * 取模判断的方式,要浪费一个队列的元素空间,就是takeIndex所指向的空间。
     * 而且使用count可以简便操作
     */
    private void enqueue(E e) {
        items[putIndex] = e;
        if (++putIndex == items.length) //实现队列的循环存取
            putIndex = 0;
        count++;
        notEmpty.signal();  //唤醒notEmpty的队列的节点到主队列中去
    }

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notFull.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

    private E dequeue() {
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E e = (E) items[takeIndex];
        items[takeIndex] = null;
        if (++takeIndex == items.length) takeIndex = 0;
        count--;
        notFull.signal();
        return e;
    }
}

2.ReentrantLock 

package tools.myBlockingQueue;



/**
 * @Auther: duanYL
 * @Date: 2023/10/11/14:39
 * @Description:
 */
public class ReentrantLock {
    private final Sync sync;

    public ReentrantLock() {
        sync = new NonfairSync();
    }

    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

    public void lock() {
        sync.acquire(1);
    }

    public void unlock() {
        sync.release(1);
    }

    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    public Condition newCondition() {
        return sync.newCondition();
    }


    abstract static class Sync extends AbstractQueuedSynchronizer {
        //因为reentrantLock是可以重入的锁,所以tryRelease并不是一定返回true的
        protected final boolean tryRelease(int releases) {

            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();

            int newState = getState() - releases;
            boolean free = false;
            if (newState == 0) {
                setExclusiveOwnerThread(null);
                free = true;
            }
            setState(newState);
            return free;
        }

        protected final boolean isHeldExclusively() {
            // While we must in general read state before owner,
            // we don't need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }
    }

    //类上加final有啥用
    static final class NonfairSync extends Sync {

        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            } else if (current == getExclusiveOwnerThread()) {
                int newState = c + acquires;
                if (newState < 0) {
                    throw new Error("Maximum lock count exceeded");
                }
                setState(newState);
                return true;
            }
            return false;
        }
    }

    static final class FairSync extends Sync {
        protected final boolean tryAcquire(int acquires) {
            Thread thread = Thread.currentThread();
            int state = getState();
            if (state == 0) {   //说明该线程是第一个竞争锁的
                if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(thread);
                    return true;
                }
            } else if (thread == getExclusiveOwnerThread()) {
                int newState = state + acquires;
                if (newState < 0) {
                    throw new Error("Maximum lock count exceeded");
                }
                setState(newState);
                return true;
            }
            return false;
        }
    }

}

 3.AbstractQueuedSynchronizer

package tools.myBlockingQueue;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * @Auther: duanYL
 * @Date: 2023/10/11/14:51
 * @Description: 该同步器的核心就是acquire方法。对于该同步器的思路来说,
 * 执行acquire方法就是入队,acquire方法执行完就是出队。
 */
public class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer {

    private transient volatile Node head;
    private transient volatile Node tail;
    private volatile int state; //同步器并没有操作该变量,而是交于实现类来操作

    // VarHandle mechanics  每个VarHandle对应一个变量,用来操作变量
    private static final VarHandle HEAD;
    private static final VarHandle TAIL;
    private static final VarHandle STATE;

    static {
        try {
            MethodHandles.Lookup l = MethodHandles.lookup();
            STATE = l.findVarHandle(AbstractQueuedSynchronizer.class, "state", int.class);
            HEAD = l.findVarHandle(AbstractQueuedSynchronizer.class, "head", Node.class);
            TAIL = l.findVarHandle(AbstractQueuedSynchronizer.class, "tail", Node.class);
        } catch (ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }
        Class<?> ensureLoaded = LockSupport.class;
    }

    protected final int getState() {
        return state;
    }

    protected final void setState(int newState) {
        state = newState;
    }

    protected final boolean compareAndSetState(int expect, int update) {
        return STATE.compareAndSet(this, expect, update);
    }

    public final void acquire(int arg) {
        /**     一.同步器并没有实现tryAcquire方法,而是由具体的实现类实现。
         *          该方法为false表示需要入队,该方法为true表示 不需要入队 或者 出队
         *          该方法就是出入队的条件,由使用者实现
         *          在ReentrantLock中,tryAcquire方法保证了同一时间只有一个线程调用该方法会返回true
         *
         *      二.addWaiter方法 实际是将线程封装成节点,放入队列里面
         *
         *      三.acquireQueued方法有两种作用 1.用来出队,2.用来阻塞当前线程
         *      1.acquireQueued方法会尝试一次出队,如果出队失败就进入睡眠
         *      2.当线程阻塞时,release方法被调用就是一次出队信号,如果符合条件该线程会被唤醒,
         *          并且满足tryAcquire的出队条件,那就出队成功
         */
        if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();    //只有acquireQueued返回的打断标记为true才会执行该方法,该方法重新給线程添上打断标记
    }


    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

    private Node addWaiter(Node mode) {
        Node node = new Node(mode);     //一个node对应一个线程,创建node时,会保存当前线程信息

        for (; ; ) {        //死循环保证node必须入队列
            Node oldTail = tail;
            if (oldTail != null) {      //初始的时候队列head和tail都指向null,oldTail不为空说明了初始化完成了
                node.setPrev(oldTail);      //这三条边的连接顺序,保证了只需要一次cas
                if (compareAndSetTail(oldTail, node)) {
                    oldTail.next = node;
                    return node;
                }
            } else {
                /** 初始化。 该队列的本质是一个双向链表,初始化完成后head和tail都指向一个空Node,
                 *  空Node用来方便出入队列,以及后续操作
                 */
                initializeSyncQueue();
            }
        }
    }

    private boolean compareAndSetTail(Node oldTail, Node newNode) {
        return TAIL.compareAndSet(this, oldTail, newNode);
    }

    private void initializeSyncQueue() {
        Node node;
        if (HEAD.compareAndSet(this, null, node = new Node())) {
            tail = node;
        }
    }

    final boolean acquireQueued(final Node node, int arg) {
        /**
         *   死循环保证一定能出队,循环时尝试出队一次,如果出队失败线程就park住,等待
         *   伴随着循环,Node中的waitStatus的变化是0->-1
         *
         *  为什么这里要单独用个interrupted变量来存。
         *  因为被打断的线程,如果不消除打断标记,那么tryAcquire失败,就再也不能park住了
         *  而消除了打断标记就必须靠其他变量来反馈回去
         */
        boolean interrupted = false;
        try {
            for (; ; ) {
                Node preNode = node.predecessor();

                //只有头结点才允许出队,(此处的头结点并不是初始化后的空节点,而是空节点后的那个节点)
                if (head == preNode && tryAcquire(arg)) {
                    setHead(node);
                    preNode.next = null;
                    return interrupted;     //返回打断标记,表明线程是正常出队还是被打断出队的
                }
                if (shouldParkAfterFailedAcquire(preNode, node))
                    interrupted |= parkAndCheckInterrupt();
            }
        } catch (Throwable t) {
            cancelAcquire(node);
            if (interrupted)
                selfInterrupt();
            throw t;
        }

    }

    private void cancelAcquire(Node node) {
        if (node == null)
            return;

        node.thread = null;
        //如果前一个节点被取消了(Node.CANCELLED=1),那就将前一个节点剔除掉
        Node prev = node.prev;
        while (prev.waitStatus > 0) {
            node.prev = prev = prev.prev;
        }

        Node prevNext = prev.next;

        node.waitStatus = Node.CANCELLED;
        
        /*  1.如果被取消的节点在空节点后的那个节点,
                那么同步器可能没有线程占用,
                剔除该节点并唤醒后一个节点。
            2.如果被取消的节点在对尾,那直接丢弃就行了
            3.如果被取消的节点在队中,也直接丢弃
         */
        if (node == tail && compareAndSetTail(node, prev)) {
            prev.compareAndSetNext(prevNext, null);
        } else {
            int ws;
            /*  三个同级且条件:要进入该if必须满足非队首对尾
                    并且不能是被取消的节点
                1.prev != head     3.prev.thread != null
                2.(ws = prev.waitStatus) == Node.SIGNAL ||
                    (ws <= 0 && prev.compareAndSetWaitStatus(ws, Node.SIGNAL))
             */
            if  (prev != head &&
                ((ws = prev.waitStatus) == Node.SIGNAL
                        || (ws <= 0 && prev.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
                prev.thread != null) {

                Node next= node.next;
                if (next != null && next.waitStatus <= 0)
                    prev.compareAndSetNext(prevNext, next);
            } else {
                //因为设置了Node.CANCELLED,执行该方法时会将node剔除
                unparkSuccessor(node);
            }
            node.next=node;
        }
    }

    public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (!tryAcquire(arg))
            doAcquireInterruptibly(arg);
    }

    private void doAcquireInterruptibly(int arg)
            throws InterruptedException {
        final Node node = addWaiter(Node.EXCLUSIVE);
        try {
            for (; ; ) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null;
                    return;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } catch (Throwable t) {
            cancelAcquire(node);
            throw t;
        }
    }

    private void setHead(Node node) {
        head = node;
        head.thread = null;
        head.prev = null;
    }

    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        /** 只修改前一个节点的值,而不修改当前节点的值
         * 也就是说前一个节点的waitStatus才是当前节点的状态
         */

        int waitStatus = pred.waitStatus;
        if (waitStatus == Node.SIGNAL) {
            return true;
        }
        if (waitStatus > 0) {
            /*
             * ws>0,说明了节点被取消了,这里将取消的节点剔除了
             */
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            pred.compareAndSetWaitStatus(waitStatus, Node.SIGNAL);
        }
        return false;
    }

    private final boolean parkAndCheckInterrupt() {
        LockSupport.park();
        return Thread.interrupted();    //返回线程是被打断唤醒还是正常唤醒,重置打断标记
    }

    private void selfInterrupt() {
        Thread.currentThread().interrupt();
    }

    public final boolean release(int arg) {
        //tryRelease方法由具体的实现类实现
        if (tryRelease(arg)) {
            Node node = head;   //node为null说明队列还未初始化
            if (node != null && node.waitStatus != 0) {
                unparkSuccessor(node);
            }
            return true;
        }
        return false;
    }

    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

    private void unparkSuccessor(Node node) {
        Node s = node.next;
        /**
         * 此处将-1改为0,如果在分公平锁的情况下,如果被唤醒的线程获取锁失败
         * 则不会直接park住,会多一次循环的机会。
         * 多一次循环的机会就会降低被park的可能性
         */
        int ws = node.waitStatus;
        if (ws < 0)
            node.compareAndSetWaitStatus(ws, 0);

        /**
         * 为什么会判断s==null,因为在真正的AbstractQueuedSynchronizer中
         * 可能该线程会出现异常情况,需要将该node删除,在删除的过程中就有可能为null
         */
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node p = tail; p != node && p != null; p = p.prev) {
                if (p.waitStatus < 0)
                    s = p;
            }
        }
        if (s != null) {
            LockSupport.unpark(s.thread);
        }
    }

    /**
     * put和take方法内有一次加锁和解锁,这里就是把put和take方法加的锁释放掉
     * 等执行acquireQueue方法的时候再尝试把锁加上
     * 如果释放失败,则抛出异常并且把该节点设为CANCELLED
     */
    final int fullyRelease(Node node) {
        try {
            int savedState = getState();
            if (release(savedState))
                return savedState;
            throw new IllegalMonitorStateException();
        } catch (Throwable t) {
            node.waitStatus = Node.CANCELLED;
            throw t;
        }
    }

    public final boolean hasQueuedPredecessors() {
        Node h, s;
        /**
         * 为什么会判断s==null,因为在真正的AbstractQueuedSynchronizer中
         * 可能该线程会出现异常情况,需要将该node删除,在删除的过程中就有可能为null
         */
        if ((h = head) != null) {
            if ((s = h.next) == null || s.waitStatus > 0) {
                s = null;
                for (Node p = tail; p != h && p != null; p = p.prev) {
                    if (p.waitStatus <= 0)
                        s = p;
                }
            }
            if (s != null && s.thread != Thread.currentThread())
                return true;

        }
        return false;
    }

    final boolean isOnSyncQueue(Node node) {
        //如果在CLH队列中,则ws就不能等于condition,condition代表的是在条件队列中
        //next和prev指针是作用在CLH队列的 , 为空说明了还未放进CLH队列中
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        //不为空,说明了连接有其他节点,则必在CLH队列中
        if (node.next != null)
            return true;
        /*  进入CLH队列,边的连接顺序是:1.node.setPrevRelaxed(oldTail);
            2.compareAndSetTail(oldTail, node)  3.oldTail.next = node;
            有可能第一步设置了prev指针指向前一个节点,但是第二步cas失败了
            也就是上面两个if条件都不满足
            这时候就需要遍历节点才能确定是否进入了队列。
            新添加的节点,通常都在尾部附近,所以从末尾开始遍历
         */
        return findNodeFromTail(node);
    }

    /**
     * 从尾部开始遍历,查找是否有目标节点node
     */
    private boolean findNodeFromTail(Node node) {
        for (Node p = tail; ; p = p.prev) {
            if (p == null)
                return false;
            if (p == node)
                return true;
        }
    }

    private static final int REINTERRUPT = 1;
    private static final int THROW_IE = -1;

    /**
     * 检查节点是否被打断了,没别打断就返回0
     * 如果被打断了,就尝试进入CLH队列
     *
     * @return 没打断0,打断之前执行了signal方法是REINTERRUPT,打断前没执行则是THROW_IE
     */
    private int checkInterruptWhileWaiting(Node node) {
        return Thread.interrupted() ?
                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                0;
    }

    /**
     * 该方法是将等待队列中的节点放进CLH队列
     * 被signal唤醒的节点,在signal里面有进入CLH队列的逻辑
     * 但是被打断的节点,只能自己进入队列里,被打断有两种情况
     * 1.直接被打断,这种一般在if判断时就会返回
     * 2.执行signal方法,但是signal方法的unpark方法还未执行时,被打断了,这种会执行while循环
     */
    final boolean transferAfterCancelledWait(Node node) {
        //当执行signal方法时,signal方法会将ws从CONDITION->0,那么这里cas会失败
        if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
            enq(node);
            return true;
        }
        //signal方法会让node入CLH队列,这里自旋等待入队成功,
        //如果不自旋,接下来的acquireQueue方法会出错
        while (!isOnSyncQueue(node))
            Thread.yield();
        return false;
    }

    /**
     * 该方法和addWaiter方法大致一样,只是addWaiter方法会先创建节点
     * 再入队,而这里是将现成的节点入队
     */
    private Node enq(Node node) {
        for (; ; ) {
            Node oldTail = tail;
            if (oldTail != null) {
                node.setPrev(oldTail);
                if (compareAndSetTail(oldTail, node)) {
                    oldTail.next = node;
                    return oldTail;
                }
            } else {
                initializeSyncQueue();
            }
        }
    }

    protected boolean isHeldExclusively() {
        throw new UnsupportedOperationException();
    }

    final boolean transferForSignal(Node node) {
        //如果cas失败,说明节点被打断唤醒了。因为打断唤醒后就会把Node.CONDITION->0
        if (!node.compareAndSetWaitStatus(Node.CONDITION, 0))
            return false;

        /*
            enq返回的节点是当前节点的前一个节点
            1.如果前一个节点的waitStatus>0,唤醒这个线程后,
            会在acquireQueue方法里面的shouldParkAfterFailedAcquire方法里面
            将前一个节点删除掉。
            2.如果前一个节点cas失败了,那么就需要唤醒这个节点让它自己在acquireQueue方法里面
            自己循环的把waitStatus改为Signal
         */
        Node p = enq(node);
        int waitStatus = p.waitStatus;
        if (waitStatus > 0 || !p.compareAndSetWaitStatus(waitStatus, Node.SIGNAL)) {
            LockSupport.unpark(node.thread);
        }
        return true;
    }

    static final class Node {
        static final Node EXCLUSIVE = null;
        static final int CANCELLED = 1;
        static final int SIGNAL = -1;
        static final int CONDITION = -2;
        volatile int waitStatus;    //节点的状态

        volatile Node prev;

        volatile Node next;

        volatile Thread thread;

        Node nextWaiter;

        private static final VarHandle NEXT;
        private static final VarHandle PREV;
        private static final VarHandle THREAD;
        private static final VarHandle WAITSTATUS;

        static {
            try {
                MethodHandles.Lookup l = MethodHandles.lookup();
                NEXT = l.findVarHandle(Node.class, "next", Node.class);
                PREV = l.findVarHandle(Node.class, "prev", Node.class);
                THREAD = l.findVarHandle(Node.class, "thread", Thread.class);
                WAITSTATUS = l.findVarHandle(Node.class, "waitStatus", int.class);
            } catch (ReflectiveOperationException e) {
                throw new ExceptionInInitializerError(e);
            }
        }

        public Node() {

        }

        public Node(Node node) {
            this.nextWaiter = node;
            THREAD.set(this, Thread.currentThread());
        }

        Node(int waitStatus) {
            WAITSTATUS.set(this, waitStatus);
            THREAD.set(this, Thread.currentThread());
        }

        public void setPrev(Node prev) {
            PREV.set(this, prev);
        }

        final Node predecessor() {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        final boolean compareAndSetWaitStatus(int expect, int update) {
            return WAITSTATUS.compareAndSet(this, expect, update);
        }

        final boolean compareAndSetNext(Node expect, Node update) {
            return NEXT.compareAndSet(this, expect, update);
        }

    }

    /**
     * 条件队列是一个单向链表,首位节点分别是firstWaiter和lastWaiter
     * 节点之间的联系则是依靠Node的nextWaiter变量
     */
    public class ConditionObject implements Condition {

        private Node firstWaiter;

        private Node lastWaiter;

        public ConditionObject() {
        }

        @Override
        public void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();   //将当前线程封装为Node添加到条件队列里
            //这里退出了对同步器的占用(相当于解锁),返回的state在下一次加锁时重新设回
            int savedState = fullyRelease(node);
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this); //让出cpu,等待被唤醒
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            /*  如果在获取队列时被打断了并且之前的状态不是THROW_IE,则会标记为REINTERRUPT
                fullyRelease释放了对同步器的占用,这里的acquireQueued则是重新获得了同步器的使用权
                也就相当于加锁了
             */
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE) {
                interruptMode = REINTERRUPT;
            }
            /*
                如果node是被signal的unpark唤醒的,signal方法内部会把nextWaiter设为空
                如果node是被打断唤醒的,那么nextWaiter必定不为空
             */
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            /*
                interruptMode 如果是 THROW_IE 则抛出异常
                interruptMode 如果是 REINTERRUPT 则给线程设置打断标记
             */
            if (interruptMode != 0) {
                reportInterruptAfterWait(interruptMode);
            }
        }

        private Node addConditionWaiter() {
            Node oldLast = lastWaiter;
            //ws不是CONDITION,则说明需要被移出条件队列
            if (oldLast != null && oldLast.waitStatus != Node.CONDITION) {
                unlinkCancelledWaiters();
                oldLast = lastWaiter;
            }
            //条件队列中添加节点
            Node node = new Node(Node.CONDITION);
            if (oldLast == null)
                firstWaiter = node;
            else
                oldLast.nextWaiter = node;
            lastWaiter = node;
            return node;
        }

        /**
         * 循环剔除掉所有状态值不是CONDITION的节点
         */
        private void unlinkCancelledWaiters() {
            /*  总共要操作5个指针
                因为条件队列是个单向链表,所以要用三个指针
                trail、t、next,用于剔除掉节点
                还有两个是firstWaiter和lastWaiter
                当删除头尾节点时,这两个指针需要重定位
             */
            Node t = firstWaiter;
            Node trail = null;
            while (t != null) {
                Node next = t.next;
                if (t.waitStatus != Node.CONDITION) {
                    t.next = null;
                    if (trail == null)
                        firstWaiter = null;
                    else
                        trail.next = next;
                    if (next == null)
                        lastWaiter = trail;
                } else {
                    trail = t;
                }
                t = next;
            }
        }

        private void reportInterruptAfterWait(int interruptMode) throws InterruptedException {
            if (interruptMode == THROW_IE)
                throw new InterruptedException();
            else if (interruptMode == REINTERRUPT)
                selfInterrupt();
        }

        @Override
        public void awaitUninterruptibly() {

        }

        @Override
        public long awaitNanos(long nanosTimeout) throws InterruptedException {
            return 0;
        }

        @Override
        public boolean await(long time, TimeUnit unit) throws InterruptedException {
            return false;
        }

        @Override
        public boolean awaitUntil(Date deadline) throws InterruptedException {
            return false;
        }

        @Override
        public void signal() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignal(first);
        }

        /**
         * 将节点从等待队列移除,并尝试通过transferForSignal方法
         * 将节点放进CLH队列中
         *
         * @param first
         */
        private void doSignal(Node first) {
            do {
                if ((firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) &&
                    (first = firstWaiter) != null);
        }

        @Override
        public void signalAll() {

        }
    }


}


总结

        主要实现了队列的take和put方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值