Java多線程系列——計數器 CountDownLatch

來源:互聯網
上載者:User

標籤:closed   ace   exception   run   hid   執行   rup   控制   protected   

簡介:

CountDownLatch 是一個非常實用的多線程式控制制工具類,通常用來控制線程的等待,它可以讓某個線程等待直到倒計時結束

CountDownLatch 提供了兩個主要的方法,await()、countDown()。

  • await:使當前線程阻塞,等待計數器為 0

  • countDown:計數器減一,計數為零時,釋放所有在等待的線程

執行個體:
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()。

CountDownLatch(int count)
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;    }  }}
View Code

其中 setState 是設定 AbstractQueuedSynchronizer 中 state 變數,該變數聲明了 volatile。

State 就是 countDownLatch 中的計數器。

await()
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。

doAcquireSharedNanos() 會使當前線程一直等待,直到當前線程擷取到共用鎖定(或線程被中斷)才返回。

countDown()
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 時,會將計數器減一。

參考資料

Java多線程系列--“JUC鎖”09之 CountDownLatch原理和樣本

 

Java多線程系列——計數器 CountDownLatch

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.