CountDownLatch
也是一個java.util.concurrent
包中的類,能夠設置一個初始數值,在數值大於0以前讓調用await()
方法的線程堵塞住,數值爲0是則會放開全部阻塞住的線程。底層基於AQS
實現,還不瞭解的能夠先看這篇 Java AQS底層原理解析 。java
public static void main(String[] args) throws InterruptedException { // 設置初始數值爲10 CountDownLatch latch = new CountDownLatch(10); // 循環中調用countDown()減1,若是調用9次則數值爲1,主線程和子線程都會阻塞,改成i<10調用10次則主線程和子線程均可以運行 for(int i=0;i<9;i++) { latch.countDown(); System.out.println(latch.getCount()); } new Thread(new Runnable() { @Override public void run() { System.out.println("thread start"); try { // 阻塞子線程 latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread end"); } }).start(); // 阻塞主線程 latch.await(); System.out.println("main end"); }
構造方法segmentfault
內部也是有個Sync
類繼承了AQS
,因此CountDownLatch
類的構造方法就是調用Sync
類的構造方法,而後調用setState()
方法設置AQS
中state
的值。ide
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); } Sync(int count) { setState(count); }
await()ui
該方法是使調用的線程阻塞住,直到state
的值爲0就放開全部阻塞的線程。實現會調用到AQS
中的acquireSharedInterruptibly()
方法,先判斷下是否被中斷,接着調用了tryAcquireShared()
方法,講AQS
那篇文章裏提到過這個方法是須要子類實現的,能夠看到實現的邏輯就是判斷state
值是否爲0,是就返回1,不是則返回-1。this
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); } protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; }
countDown()線程
這個方法會對state
值減1,會調用到AQS
中releaseShared()
方法,目的是爲了調用doReleaseShared()
方法,這個是AQS定義好的釋放資源的方法,而tryReleaseShared()
則是子類實現的,能夠看到是一個自旋CAS
操做,每次都獲取state
值,若是爲0則直接返回,不然就執行減1的操做,失敗了就重試,若是減完後值爲0就表示要釋放全部阻塞住的線程了,也就會執行到AQS
中的doReleaseShared()
方法。code
public void countDown() { sync.releaseShared(1); } public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; } protected boolean tryReleaseShared(int releases) { // Decrement count; signal when transition to zero for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; } }