static class Node<E> {
E item ;/*** One of:* - the real successor Node* - this Node, meaning the successor is head.next* - null, meaning there is no successor (this is the last node)*/Node < E > next ;Node ( E x ) { item = x ; }}
private transient Node < E > head ; /* 头结点, 头节点不保存数据信息 */private transient Node < E > last ; /* 尾节点, 尾节点保存最新入队的数据信息 */
private final int capacity; /* 队列容量一般使用中,构造LinkedBlockingQueue时,需要传入当前队列大小,如果不传入,默认是Integer.MAX_VALUE */
private final AtomicInteger count = new AtomicInteger ( 0 ); // 队列当前大小
private final ReentrantLock takeLock = new ReentrantLock (); /* 读锁 */private final Condition notEmpty = takeLock . newCondition (); /* 读锁对应的条件 */private final ReentrantLock putLock = new ReentrantLock (); /* 写锁 */private final Condition notFull = putLock . newCondition (); /* 写锁对应的条件 */
private void enqueue(E x) {
last = last . next = new Node < E >( x );}
private void enqueue(E x) {
Node<E> newNode = new Node<E>(x); /* 新建一个Node对象,此对象的数据部分是新元素的指针,next指针为null */
last . next = newNode ; /* 将目前list节点的next指针指向新对象 */last = last . next ; /* 将last指针向后移动一个元素,指向新的尾端 */}
private E dequeue () {Node < E > h = head ; /* 记录目前头节点的指针 */Node < E > first = h . next ; /* 得到头结点后的第一个节点,即需要出队的数据节点 *//* 将需要出队的数据的尾节点设置为自己,让此对象变为孤立对象,GC可以进行回收,更重要的是,如果 迭代器引用此节点,迭代器可以通过判断next是否等于自己,来了解迭代器的下一个节点是否应该重定向为头节点 */h . next = h ;head = first ; /* 将头指针指向新的头节点 */E x = first . item ; /* 获取数据元素的内容 *//* 将头节点所在数据元素设置为null,因为头节点的数据已出队,如果此时再持有其引用,可能造成内存泄漏 */
first . item = null ;return x ;}
offer的算法与put类似,这里不再赘述。public void put ( E e ) throws InterruptedException {if ( e == null ) throw new NullPointerException ();int c = - 1 ;final ReentrantLock putLock = this . putLock ;final AtomicInteger count = this . count ;putLock . lockInterruptibly ();try {while ( count . get () == capacity ) {notFull . await ();}enqueue ( e );c = count . getAndIncrement ();if ( c + 1 < capacity )notFull . signal (); /* 如果完成当前入队操作后,队列依然有剩余的空间,那么再唤醒另一个等待入队的线程 */} finally {putLock . unlock ();}if ( c == 0 ) /* 如果入队前,队列大小为空,那么唤醒一个等待出队的线程 */signalNotEmpty ();}
public E take () throws InterruptedException {E x ;int c = - 1 ;final AtomicInteger count = this . count ;final ReentrantLock takeLock = this . takeLock ;takeLock . lockInterruptibly ();try {while ( count . get () == 0 ) {notEmpty . await ();}x = dequeue ();c = count . getAndDecrement ();if ( c > 1 )notEmpty . signal (); /* 如果完成当前入队操作后,队列依然有剩余的元素,那么再唤醒另一个等待出队的线程 */} finally {takeLock . unlock ();}if ( c == capacity )signalNotFull (); /* 如果出队前,队列是满的,那么出队后,队列就空了,需要通知一个等待入队的线程 */return x ;}
void fullyLock() {
putLock . lock (); // 先加写锁takeLock.lock(); // 再加读锁}
void fullyUnlock () {takeLock . unlock (); /* 先解锁读锁 */putLock . unlock (); /* 再解锁写锁 */}
private Node<E> current; /* 迭代器的下一个位置 */
private Node < E > lastRet ; /* 当前迭代器的位置 */private E currentElement ; /* 当前需要返回的元素内容 */