CountDownLatch 是一個很是實用的多線程控制工具類,一般用來控制線程的等待,它能夠讓某個線程等待直到倒計時結束html
CountDownLatch 提供了兩個主要的方法,await()、countDown()。多線程
await:使當前線程阻塞,等待計數器爲 0dom
countDown:計數器減一,計數爲零時,釋放全部在等待的線程ide
public class CountDownLatchDemo implements Runnable { static final CountDownLatch end = new CountDownLatch(10); static final CountDownLatchDemo demo = new CountDownLatchDemo(); @Override public void run() { try { Thread.sleep(new Random().nextInt(10) * 1000); System.out.println("check complete..."); end.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { ExecutorService exec = Executors.newFixedThreadPool(10); for (int i = 0;i < 10;i++) { exec.submit(demo); } end.await(); System.out.println("Fire!"); exec.shutdown(); } }
countDownLatch 的計數是經過一個共享變量(volatile)實現的,下面分析它的三個核心函數:構造函數,CountDownLatch(int count);阻塞線程,await();計數器減一,countDown()。函數
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); }
其中 Sync 是 CountDownLatch 的內部類,而且 Sync 繼承了 AbstractQueuedSynchronizer工具
private static final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L; Sync(int count) { setState(count); } int getCount() { return getState(); } protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; } 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; } } }
其中 setState 是設置 AbstractQueuedSynchronizer 中 state 變量,該變量聲明瞭 volatile。post
State 就是 countDownLatch 中的計數器。ui
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); return tryAcquireShared(arg) >= 0 || doAcquireSharedNanos(arg, nanosTimeout); }
acquireSharedInterruptibly() 的做用是獲取共享鎖,若是當前線程處於中斷狀態,則拋出 InterruptedException,不然,調用 tryAcquireShared(arg) 嘗試獲取共享鎖,若是鎖計數器 = 0,則表示鎖爲可獲取狀態,返回 1,不然,鎖爲不可獲取狀態,則返回 -1。this
doAcquireSharedNanos() 會使當前線程一直等待,直到當前線程獲取到共享鎖(或線程被中斷)才返回。url
public void countDown() { sync.releaseShared(1); } public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; }
releaseShared() 目的是讓當前線程釋放它所持有的共享鎖。
tryReleaseShared() 的做用是釋放共享鎖,將鎖計數器的值減一。
CountDownLatch 是經過共享鎖實現的。CountDownLatch 構造函數傳遞 int 參數,該參數是計數器的初始狀態,表示共享鎖最多能被 count 個線程同時獲取。
當某線程調用 CountDownLatch 的 await 方法時,該線程會等待共享鎖可用時(計數器爲 0 時),才能獲取共享鎖,進而繼續執行。
每次執行 countDown 時,會將計數器減一。