JDK7中SynchronousQueue源码解析

来源:互联网 发布:ubuntu和redhat的区别 编辑:程序博客网 时间:2024/05/17 23:34
SynchronousQueue<E>是java.util.concurrent包下的阻塞队列类,是Java Collections Framework的成员,其中每个插入操作必须等待另一个线程的对应移除操作,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。不能在同步队列上进行peek,因为仅在试图要移除元素时,该元素才存在;除非另一个线程试图移除某个元素,否则也不能使用任何方法插入元素;也不能迭代队列,因为其中没有元素可用于迭代。队列的头是尝试添加到队列中的首个已排队插入线程的元素;如果没有这样的已排队线程,则没有可用于移除的元素并且poll()将会返回null。对于其它Collection方法,例如contains,SynchronousQueue作为一个空collection。队列不允许null元素。

SynchronousQueue<E>非常适合于传递性设计,在线程中运行的对象要将某些信息,事件或任务传递给在另外线程中运行的对象,它就必须与该对象同步。对于正在等待的生产者和使用者线程而言,此类支持可选的公平排序策略。默认情况下不保证这种排序。但是使用公平设置为true所构造的队列可保证线程以FIFO的顺序进行访问。此类及其迭代器实现Collection和Iterator接口的所有可选方法。

运用实现可参考:https://github.com/chunericli/wise-utils,相对于ArrayBlockingQueue和LinkedBlockingQueue而言,SynchronousQueue<E>的运用和实现相对比较复杂。SynchronousQueue<E>提供的实现方法虽然在行为上有不少差异,但是其底层实现极其相似,SynchronousQueue<E>提供的方法不多,其API提供【插入,获取和移除】和差别概述如下所示:

构造函数:
SynchronousQueue():创建一个具有非公平访问策略的SynchronousQueue。
SynchronousQueue(boolean fair):创建一个具有指定公平策略的SynchronousQueue。

移除元素:
int drainTo(Collection<? super E> c):移除队列中所有可用元素,并将其添加到给定collection中。
int drainTo(Collection<? super E> c, int maxElements):最多从队列中移除给定数量的可用元素,并将这些元素添加到给定collection中。
boolean remove(Object o):始终返回false。
boolean removeAll(Collection<?> c):始终返回false。
void clear():不执行任何操作。 

插入元素:
boolean offer(E e):如果另一个线程正在等待以便接收指定元素,则将指定元素插入到此队列。
boolean offer(E o, long timeout, TimeUnit unit):将指定元素插入到此队列,如有必要则等待指定的时间,以便另一个线程接收它。
void put(E o):将指定元素添加到此队列,如有必要则等待另一个线程接收它。

获取元素:
E peek():始终返回null。
E poll():如果另一个线程当前正要使用某个元素,则获取并移除此队列的头。
E poll(long timeout, TimeUnit unit):获取并移除此队列的头,如有必要则等待指定的时间,以便另一个线程插入它。
E take():获取并移除此队列的头,如有必要则等待另一个线程插入它。

SynchronousQueue<E>实现了Scherer和Scott的"非阻塞并发对象与条件同步"中描述的双堆栈和双队列算法的扩展。关于非阻塞并发对象与条件同步算法可自行参考:http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/duals.html。栈(LIFO)用于非公平模式,队列(FIFO)用于公平模式,两者的性能通常是相似的。FIFO通常支持在争用下提高吞吐量,但是LIFO在通用应用程序中维护更高的线程位置。

双队列(以及类似的堆栈)是在任何给定时间内保存"数据"【通过put操作提供的items或者"请求"代表操作的slots】或者是空的。调用"完成"(即请求从队列中保存数据或反之亦然的请求)出队列的互补节点。这些队列最有趣的特性是,任何操作都可以计算出队列所在的模式,并在不需要锁的情况下采取相应的操作。队列和堆栈都扩展抽象类Transferer,定义执行put或take的单个方法transfer。由于在双数据结构中,put和take操作是对称的,所以几乎所有的代码都可以组合在一起。由此产生的transfer方法在较长一段时间内,但如果分解成几乎重复的部分,则比它们更容易遵循。队列和堆栈数据结构具有许多概念上的相似性,但具体细节很少。为了简单起见,它们是保持不同的,这样它们就可以单独演化。这里的算法不同于上面的内容中的版本,用于扩展它们以在同步队列中使用,以及处理取消。主要的差异包括:
(1)最初的算法使用了位标记指针,但是这里的这些算法在节点中使用模式位,从而导致了一些进一步的适应。
(2)同步队列必须阻塞等待实现的线程。
(3)通过超时和中断支持取消,包括清理已取消的节点/线程,以避免垃圾保留和内存耗尽。

SynchronousQueue<E>主要是使用LockSupport.park/unpark来完成阻塞相关操作的,除了那些看起来是接下来要实现的节点(spin a bit,仅在多处理器上)。在非常繁忙的同步队列中,自旋可以显著提高吞吐量。而在不太忙碌的情况下,自旋量很小,不值得注意。在队列vs堆栈中,以不同的方式进行清理。对于队列,当它被取消时,几乎可以在O(1)时间内立即删除一个节点(模块重试的一致性检查)。但如果它可以被固定为当前的尾节点,它必须等到随后的一些取消。对于堆栈,需要可能O(n)遍历以确保可以删除节点,但这可以与访问堆栈的其它线程同时运行。

虽然垃圾回收处理了大多数节点回收问题,但这些问题使得非阻塞算法变得复杂,但是关注的是"forget"对数据,其它节点和可能被阻塞的线程长期持有的线程的引用。如果在设置为null的情况下与主算法发生冲突,则通过更改节点的链接到节点本身来完成。对于堆栈节点(因为阻塞的线程不挂在老的head指针上),这并没有多大的影响,但是队列节点中的引用必须被积极地遗忘,以避免到达后所提到的任何节点的可达性。

SynchronousQueue<E>源码解析:

public class SynchronousQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable {
 abstract static class Transferer{
   // 双堆栈和双队列的内部API,用来执行put和take操作
   abstract Object transfer(Object e, boolean timed, long nanos);
 }

 static final int NCPUS = Runtime.getRuntime().availableProcessors(); 

 // 应该是用于自旋控制的cpu数量

 static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32; // 阻塞前的自旋次数控制
 static final int maxUntimedSpins = maxTimedSpins * 16; // 不用在自旋时检查是否超时
 static final long spinForTimeoutThreshold = 1000L;

 static final class TransferStack extends Transferer{
   static final int REQUEST = 0; // 未实现的消费者
   static final int DATA = 1; // 未实现的生产者
   static final int FULFILLING = 2; // 实现其它未实现的DATA or REQUEST

   static boolean isFulfilling(int m) { return (m&FULFILLING)!=0; }

   static final class SNode{
     volatile SNode next;        // next node in stack
     volatile SNode match;       // the node matched to this
     volatile Thread waiter;     // to control park/unpark
     Object item;                // data; or null for REQUESTs
     int mode; // item和mode不需要是volatile或者volatile/atomic操作,因为总是写在前读在后
     volatile SNode head; // 栈的头节点
     SNode(Object item) { this.item=item; }

// 将节点推到栈是懒加载创建以及在可能的情况下被重用,可帮助减少读取和CASes之间的间隔,并避免在发生争用时导致节点失败的情况。

     static SNode snode(SNode s, Object e, SNode next, int mode){ 

       // 创建或重置节点字段,只从transfer中被调用

       if(s==null) s=new SNode(e);
       s.mode = mode;
       s.next = next;
       return s;
     }

     boolean casHead(SNode h, SNode nh){ // (this==h)=>(this==nh)
       return h==head&&UNSAFE.compareAndSwapObject(this, headOffset, h, nh);
     }
     boolean casNext(SNode cmp, SNode val){
       return cmp==next&&UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
     }
     void tryCancel(){ // 试图取消对其本身的匹配节点的等待
       UNSAFE.compareAndSwapObject(this, matchOffset, null, this);
     }
     boolean isCancelled(){ return match == this; }

// 试图将节点s匹配到该节点,如果是则唤醒线程。Fulfillers调用tryMatch来识别它们的waiters,waiters将被阻塞直到被匹配为止。
     boolean tryMatch(SNode s){
       if(match==null&&UNSAFE.compareAndSwapObject(this, matchOffset, null, s)){ 
          Thread w=waiter;
          if(w!=null){    // waiters need at most one unpark
             waiter=null;
             LockSupport.unpark(w); 
          }
          return true;
       }
       return match==s; 
     }

     private static final sun.misc.Unsafe UNSAFE;
     private static final long matchOffset;
     private static final long nextOffset;
     static{ // 通过UNSAFE实现内存偏移量的初始化
       try{
          UNSAFE=sun.misc.Unsafe.getUnsafe();
          Class k=SNode.class;
          matchOffset=UNSAFE.objectFieldOffset(k.getDeclaredField("match"));
          nextOffset=UNSAFE.objectFieldOffset(k.getDeclaredField("next"));
       }catch(Exception e){
          throw new Error(e);
       }
     }
   // SNode是TransferStack的内部类,此处节点作用类似AQS的CLH队列,辅助实现类【个人理解】
   }

// 如果显然是空的或者已经包含了相同模式的节点,那么尝试在堆栈上推送节点,等待匹配,返回该节点,如果取消则返回null;如果明显包含互补模式的节点,尝试将一个实现节点推送到堆栈上,与对应的等待节点匹配,从堆栈中弹出,并返回匹配项。由于其它线程执行动作3,因此可能不需要匹配或解除链接;如果堆栈顶部已经拥有另一个满足的节点,通过执行它的匹配和/或pop操作来帮助它,然后继续。帮助的代码基本上与实现相同,只是它没有返回项目。

   Object transfer(Object e, boolean timed, long nanos){ 

     // TransferStack核心方法,用来实现插入或获取元素

     SNode s=null; // 根据需要构造或者重用
     int mode=(e==null)?REQUEST:DATA; // 未实现的消费者或者是生产者
     for(;;){ // 循环调用,其实是自旋【个人理解】
       SNode h = head;
       if(h==null||h.mode==mode){ // 空或者是相同模式
         if(timed&&nanos<=0){ // 不等待
           if (h!=null&&h.isCancelled()) // 尝试在堆栈上推送节点,等待匹配,返回该节点
             casHead(h,h.next); // 弹出取消的节点
           else
             return null; // 如果取消则返回null
         }else if(casHead(h, s=snode(s,e,h,mode))){
           SNode m=awaitFulfill(s,timed,nanos);
           if(m==s){ // wait was cancelled
             clean(s);
             return null;
           }
           if((h=head)!=null&&h.next==s)
             casHead(h, s.next); // help s's fulfiller
           return (mode == REQUEST) ? m.item : s.item;
         }
       }else if(!isFulfilling(h.mode)){ // try to fulfill
          if(h.isCancelled()) // already cancelled
            casHead(h,h.next); // pop and retry
          else if(casHead(h,s=snode(s,e,h,FULFILLING|mode))){
            for(;;){ // loop until matched or waiters disappear
              SNode m=s.next; // m is s's match
              if(m==null){ // all waiters are gone
                casHead(s,null); // pop fulfill node
                s=null; // use new node next time
                break; // restart main loop
              }
              SNode mn=m.next;
              if(m.tryMatch(s)){
                casHead(s,mn); // pop both s and m
                return(mode==REQUEST)?m.item:s.item;
              } else // lost match
               s.casNext(m,mn); // help unlink
            }
          }
       }else{ // 栈顶部已经存在实现的节点 
          SNode m=h.next; // m is h's match
          if(m=null) // waiter is gone
            casHead(h,null); // pop fulfilling node
          else{
            SNode mn=m.next;
            if(m.tryMatch(h)) // help match
              casHead(h,mn); // pop both h and m
            else // lost match
              h.casNext(m,mn); // help unlink
          }
       }
     }
   }

// 当节点/线程要阻塞时,首先设置waiter字段,然后在实际阻塞前至少再重新检查一次状态,因此覆盖race vs fulfiller注意到waiter是非空的,所以应该被唤醒。当被节点在堆栈的顶端调用时,调用park之前是自旋,以避免在生产者和消费者及时到达时阻塞。这种情况只会发生在多处理器上。从主循环中返回的检查顺序反映了一个事实,即中断优先于正常的返回,这优先于超时(因此在超时时,在放弃前最后检查匹配)。除了来自不定时同步队列的调用。{poll/offer}不要检查中断,不要等待,所以被困在transfer方法中,而不是调用awaitFulfill。
   SNode awaitFulfill(SNode s,boolean timed,long nanos){ // 自旋/阻塞直到节点被完成操作匹配到
     long lastTime=timed?System.nanoTime():0;
     Thread w=Thread.currentThread();
     SNode h=head;
     int spins=(shouldSpin(s)?(timed?maxTimedSpins:maxUntimedSpins):0);
     for(;;){
       if(w.isInterrupted())
         s.tryCancel();
       SNode m=s.match;
       if(m!=null)
         return m;
       if(timed){
         long now=System.nanoTime();
         nanos-=now-lastTime;
         lastTime=now;
         if(nanos<=0){
           s.tryCancel();
           continue;
         }
       }
       if(spins>0)
         spins=shouldSpin(s)?(spins-1):0;
       else if(s.waiter==null)
         s.waiter=w; // establish waiter so can park next iter
       else if(!timed)
         LockSupport.park(this);
       else if(nanos>spinForTimeoutThreshold)
         LockSupport.parkNanos(this, nanos);
     }
   } 

   boolean shouldSpin(SNode s) { // 头节点或者存在活跃的fulfiller则返回成功
     SNode h = head;
     return (h == s || h == null || isFulfilling(h.mode));
   }

// 在最坏的情况下,可能需要遍历整个堆栈来unlink s。如果存在多个并发调用来清理,可能不会看到其它线程已经删除了它。但是可以在看到任何已知的节点时停止调用s。使用s.next除非它也被取消,在这种情况下会尝试一个过去的节点。没有进一步检查,因为不想为了找到sentinel而加倍地遍历。
   void clean(SNode s){ // Unlinks s from the stack
     s.item = null; // forget item
     s.waiter = null; // forget thread
     SNode past = s.next;
     if(past != null && past.isCancelled())
       past = past.next;
     SNode p; // Absorb cancelled nodes at head
     while ((p = head) != null && p != past && p.isCancelled())
       casHead(p, p.next);
     while (p != null && p != past) { // Unsplice embedded nodes
       SNode n = p.next;
       if(n != null && n.isCancelled())
         p.casNext(n, n.next);
       else
         p = n;
     }
   }

   private static final sun.misc.Unsafe UNSAFE;
   private static final long headOffset;
   static{
     try{
       UNSAFE=sun.misc.Unsafe.getUnsafe();
       Class k=TransferStack.class;
       headOffset=UNSAFE.objectFieldOffset(k.getDeclaredField("head"));
     }catch(Exception e){
       throw new Error(e);
     }
   }
 // TransferStack的实现比较复杂,但是底层不复杂【是CAS+Node节点来实现】,由于需要考虑情形多,故实现并不容易。
 }

 static final class TransferQueue extends Transferer {
   static final class QNode {
     volatile QNode next; // next node in queue
     volatile Object item; // CAS'ed to or from null
     volatile Thread waiter; // to control park/unpark
     final boolean isData;
     QNode(Object item, boolean isData) {
       this.item = item;
       this.isData = isData;
     }

     boolean casNext(QNode cmp, QNode val) {
       return next == cmp && UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
     }
     boolean casItem(Object cmp, Object val) {
       return item == cmp && UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
     }
     void tryCancel(Object cmp) { // 试图以CAS引用来取消此item
       UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this);
     }
     boolean isCancelled() { return item == this; }
     boolean isOffList() { // 如果节点已被队列取消则返回true,因为它的下一个指针由于advanceHead操作而被遗忘。
       return next == this;
     }

     private static final sun.misc.Unsafe UNSAFE;
     private static final long itemOffset;
     private static final long nextOffset;
     static{
       try{
          UNSAFE = sun.misc.Unsafe.getUnsafe();
          Class k = QNode.class;
          itemOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("item"));
          nextOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("next"));
       }catch(Exception e){
          throw new Error(e);
       }
     }
   }

   transient volatile QNode head; // Head of queue
   transient volatile QNode tail; // Tail of queue
   transient volatile QNode cleanMe; // 引用已被取消的节点,该节点可能还没有从队列中删除,因为它是在它被取消时最后插入的节点。
   TransferQueue() {
     QNode h = new QNode(null, false); // initialize to dummy node.
     head = h;
     tail = h;
   }

   void advanceHead(QNode h, QNode nh) { 

     // 试图cas nh作为新的head节点;如果成功则释放旧的head节点的next节点以避免GC保留

     if(h == head && UNSAFE.compareAndSwapObject(this, headOffset, h, nh))
       h.next = h; // forget old next
   }
   void advanceTail(QNode t, QNode nt) { // Tries to cas nt as new tail
     if(tail == t) UNSAFE.compareAndSwapObject(this, tailOffset, t, nt);
   }
   boolean casCleanMe(QNode cmp, QNode val) { // Tries to CAS cleanMe slot
     return cleanMe == cmp && UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
   }

// 如果队列显然包含等待项,而这个调用是互补模式,则尝试在等待节点的CAS item字段中执行,并将其排出,然后返回匹配项。在每种情况下,检查并试着代表其它被搁置/慢的线程帮助advance head and tail。循环从null检查开始,防止看到未初始化的头部或尾部值。这在当前的同步队列中是不会发生的,但是如果调用者持有non-volatile/final ref则可能。无论如何,检查都在这里,因为它将空检查放在循环的顶部,这通常比让它们隐式插入要快。
   Object transfer(Object e, boolean timed, long nanos) { // Puts or takes an item
     QNode s = null; // constructed/reused as needed
     boolean isData = (e != null);
     for(;;){
       QNode t = tail;
       QNode h = head;
       if(t==null||h==null) // 未被初始化的值
         continue; // spin
       if(h == t||t.isData==isData) { // 空或持有相同模式的节点
         QNode tn = t.next;
         if(t!=tail) continue; // 读不一致   
         if(tn != null){ // lagging tail
           advanceTail(t, tn);
           continue;
         }
         if(timed&&nanos<=0) return null; // can't wait
         if(s==null) s = new QNode(e,isData);
         if(!t.casNext(null, s)) // failed to link in
           continue;
         advanceTail(t, s); // swing tail and wait
         Object x = awaitFulfill(s, e, timed, nanos);
         if(x == s){ // wait was cancelled
           clean(t, s);
           return null;
         }
         if(!s.isOffList()) { // not already unlinked
           advanceHead(t, s); // unlink if head
           if(x!=null) // and forget fields
             s.item = s;
           s.waiter = null;
         } // 尝试将节点添加到等待服务的队列中,等待完成(或取消)并返回匹配项
         return (x != null) ? x : e;
       }else{ // complementary-mode
         QNode m = h.next; // node to fulfill
         if(t!=tail||m == null||h!= head)
           continue; // inconsistent read
         Object x = m.item;
         if(isData==(x != null)||  // m already fulfilled
             x == m ||             // m cancelled
             !m.casItem(x, e)) {   // lost CAS
            advanceHead(h, m);     // dequeue and retry
            continue;
         }
         advanceHead(h, m); // successfully fulfilled
         LockSupport.unpark(m.waiter);
         return (x != null) ? x : e;
       }
     }
   }

   Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) { 

     // 自旋/阻塞直到节点fulfilled

     long lastTime = timed ? System.nanoTime() : 0;
     Thread w = Thread.currentThread();
     int spins = ((head.next == s) ? (timed ? maxTimedSpins : maxUntimedSpins) : 0);
     for(;;){
       if (w.isInterrupted()) s.tryCancel(e);
       Object x = s.item;
       if (x != e) return x;
       if(timed){
         long now = System.nanoTime();
         nanos -= now - lastTime;
         lastTime = now;
         if(nanos <= 0){
           s.tryCancel(e); continue;
         }
       }
       if(spins > 0) --spins;
       else if (s.waiter == null) s.waiter = w;
       else if (!timed) LockSupport.park(this);
       else if (nanos > spinForTimeoutThreshold)
         LockSupport.parkNanos(this, nanos);
     }
   }

// 在任何给定的时间,不能删除list上的最后插入的节点。为适应这点,如果不能删除s则将其前继节点保存为"cleanMe",删除先前保存的版本。至少存在节
点s或之前保存的节点可以被删除,所以这个总是终止。
   void clean(QNode pred, QNode s) { // 摆脱前继节点s和原始前继节点pred
     s.waiter = null; // forget thread
     while (pred.next == s) { // Return early if already unlinked
       QNode h = head;
       QNode hn = h.next; // Absorb cancelled first node as head
       if(hn != null && hn.isCancelled()){
         advanceHead(h, hn); continue;
       }
       QNode t = tail; // Ensure consistent read for tail
       if(t == h)  return;
       QNode tn = t.next;
       if (t != tail) continue;
       if(tn != null) {
         advanceTail(t, tn);
         continue;
       }
       if(s != t){ // If not tail, try to unsplice
         QNode sn = s.next;
         if(sn == s || pred.casNext(s, sn)) return;
       }
       QNode dp = cleanMe;
       if(dp != null){ // Try unlinking previous cancelled node
         QNode d = dp.next;
         QNode dn;
         if(d == null ||          // d is gone or
            d == dp ||            // d is off list or
            !d.isCancelled() ||   // d not cancelled or
            (d!=t &&              // d not tail and
               (dn = d.next) != null &&  // has successor
                dn != d &&               // that is on list
                dp.casNext(d, dn)))      // d unspliced
            casCleanMe(dp, null);
         if(dp == pred) return; // s is already saved node
       }else if(casCleanMe(null,pred))
         return; // Postpone cleaning s
     }
   }

   private static final sun.misc.Unsafe UNSAFE;
   private static final long headOffset;
   private static final long tailOffset;
   private static final long cleanMeOffset;
   static{
     try{
       UNSAFE = sun.misc.Unsafe.getUnsafe();
       Class k = TransferQueue.class;
       headOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("head"));
       tailOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("tail"));
       cleanMeOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("cleanMe"));
     }catch(Exception e){
        throw new Error(e);
     }
   }
 // TransferQueue的实现也比较复杂,但是底层同样不复杂【是CAS+Node节点来实现】。
 }

// 只在构造函数中设置但不能声明为final而让序列化不会更加复杂。由于最多只在公共方法中访问一次,因此在使用volatile而不是final时没有明显的性能
损失。
 private transient volatile Transferer transferer;

 public SynchronousQueue(boolean fair) { // 默认为false
   transferer = fair ? new TransferQueue() : new TransferStack();
 }

 public void put(E o) throws InterruptedException { 

   // 插入元素到队列,为其它线程接收元素,等待如有必要

   if (o == null) throw new NullPointerException();
   if (transferer.transfer(o, false, 0) == null) {
     Thread.interrupted();
     throw new InterruptedException();
   }
 }

 // 插入元素到队列,为其它线程接收元素,等待如有必要,具有等待时限
 public boolean offer(E o, long timeout, TimeUnit unit)throws InterruptedException {
   if(o == null) throw new NullPointerException();
   if(transferer.transfer(o, true, unit.toNanos(timeout)) != null)
     return true;
   if(!Thread.interrupted())
     return false;
   throw new InterruptedException();
 }

 public boolean offer(E e) { // 插入元素到队列,为其它线程接收元素,等待如有必要
   if(e == null) throw new NullPointerException();
     return transferer.transfer(e, true, 0) != null;
 }

 public E take() throws InterruptedException { 

   // 检索和移除队列头节点,为其它线程插入,等待如有必要

   Object e = transferer.transfer(null, false, 0);
   if (e != null) return (E)e;
   Thread.interrupted();
   throw new InterruptedException();
 }

 // 检索和移除队列头节点,为其它线程插入,等待如有必要,具有等待时限
 public E poll(long timeout, TimeUnit unit) throws InterruptedException {
   Object e = transferer.transfer(null, true, unit.toNanos(timeout));
   if(e != null || !Thread.interrupted())
      return (E)e;
   throw new InterruptedException();
 }
 
 public int drainTo(Collection<? super E> c, int maxElements) { // 将队列中的元素复制到集合中 
   if(c == null) throw new NullPointerException();
   if(c == this) throw new IllegalArgumentException();
   int n = 0;
   E e;
   // 同drainTo(Collection<? super E> c)的实现差异在于:n < maxElements的判断
   while(n < maxElements && (e = poll()) != null) {
     c.add(e); 
     ++n; 
   }
   return n;
 } 
 // SynchronousQueue提供的方法的实现是Transferer.transferer()方法的灵活运用
}

实现总结:SynchronousQueue内部维护了Transferer对象,可根据SynchronousQueue(boolean fair)构造函数对公平性的设置,Transferer可初始化为TransferQueue【true】,TransferStack【默认false】,SynchronousQueue所提供的所有方法的实现【插入和获取元素】几乎全部交由Transferer的transferer(Object e, boolean timed, long nanos)方法实现。Transferer的底层由LockSupport,CAS和内置的Node来实现的,通过CAS Head节点来实现获取或者插入元素。
阅读全文
0 0
原创粉丝点击