Java并发之CountDownLatch原理和示例_动力节点Java学院整理

  

  

CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待只
  

  

<强> CountDownLatch和CyclicBarrier的区别

  

(01) CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。

  

(02) CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的障碍。

  

关于CyclicBarrier的原理,后面一章再来学习。

  

  

CountDownLatch (int数)

  

构造一个用给定计数初始化的CountDownLatch。

     //使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。   空白等待()//使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。   布尔等待(长超时,TimeUnit unit)//递减锁存器的计数,如果计数到达零,则释放所有等待的线程。   无效的倒计时()//返回当前计数。   长getCount ()//返回标识此锁存器及其状态的字符串。   字符串toString ()      

  

CountDownLatch的UML类图如下:

  

癑ava并发之CountDownLatch原理和示例_动力节点Java学院整理"

  

CountDownLatch的数据结构很简单,它是通过“共享锁”实现的。它包含了同步对象,同步是同步类型.Sync是实例类,它继承于aq只,
  

  

<强> 1。CountDownLatch (int数)

        公共CountDownLatch (int数){   如果(计数& lt;0)把新IllegalArgumentException(“数& lt;0”);   这一点。同步=new同步(数);   }      

说明:该函数是创建一个同步对象,而同步是继承于aq类.Sync构造函数如下:

        同步(int数){   设置状态(数);   }      

设置状态()在aq中实现,源码如下:

        保护最后的空白设置状态(长newState) {   状态=newState;   }      

说明:在aq中,国家是一个私人波动长类型的对象。对于CountDownLatch而言,状态表示的“锁计数器”.CountDownLatch中的getCount()最终是调用aq中的getState(),返回的状态对象,即“锁计数器”只
  

  

<强> 2。等待()

        公共空间等待()抛出InterruptedException {   sync.acquireSharedInterruptibly (1);   }      

说明:该函数实际上是调用的aq的acquireSharedInterruptibly (1),

  

aq中的acquireSharedInterruptibly()的源码如下:

        公众最终无效acquireSharedInterruptibly arg(长)   抛出InterruptedException {   如果(Thread.interrupted ())   抛出InterruptedException ();   如果(tryAcquireShared (arg) & lt;0)   doAcquireSharedInterruptibly (arg);   }      

说明:acquireSharedInterruptibly()的作用是获取共享锁。

  

如果当前线程是中断状态,则抛出异常InterruptedException。否,则调用tryAcquireShared (arg)尝试获取共享锁;尝试成功则返回,否则就调用doAcquireSharedInterruptibly () .doAcquireSharedInterruptibly()会使当前线程一直等待,直到当前线程获取到共享锁(或被中断)才返回。

  

tryAcquireShared()在CountDownLatch。java中被重写,它的源码如下:
  

        保护int tryAcquireShared (int获得){   返回(getState ()==0) & # 63;1:1;   }      

说明:tryAcquireShared()的作用是尝试获取共享锁。

  

如果”锁计数器=0”,即锁是可获取状态,则返回1;否,则锁是不可获取状态,则返回1 .

        私人空间doAcquireSharedInterruptibly arg(长)   抛出InterruptedException {//创建“当前线程”的节点节点,且节点中记录的锁是“共享锁”类型;并将该节点添加到CLH队列末尾。   最后一个节点节点=addWaiter (Node.SHARED);   布尔失败=true;   尝试{   (,) {//获取上一个节点。//如果上一节点是CLH队列的表头,则“尝试获取共享锁”。   最后一个节点p=node.predecessor ();   如果(p==头){   长r=tryAcquireShared (arg);   如果(r祝辞=0){   setHeadAndPropagate(节点,r);   p。下一个=零;//帮助GC   失败=false;   返回;   }   }//(上一节点不是CLH队列的表头)当前线程一直等待,直到获取到共享锁。//如果线程在等待过程中被中断过,则再次中断该线程(还原之前的中断状态)。   如果(shouldParkAfterFailedAcquire (p,节点),,   parkAndCheckInterrupt ())   抛出InterruptedException ();   }   最后}{   如果(失败)   cancelAcquire(节点);   }   }

Java并发之CountDownLatch原理和示例_动力节点Java学院整理