1. CountDownLatch end = new CountDownLatch(N); //构造对象时候 需要传入参数N
  2. end.await() 能够阻塞线程 直到调用N次end.countDown() 方法才释放线程
  3. end.countDown() 可以在多个线程中调用 计算调用次数是所有线程调用次数的总和

底层实现

  • 基于AQS 来实现共享锁

public class CountDownLatch {
    /**
     * Synchronization control For CountDownLatch.
     * Uses AQS state to represent count.
     */
    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;
            }
        }
    }

    private final Sync sync;

    //.....
}

使用

/**
* CountDownLatch 门闩
*/
public class Test_03 {
  public static void main(String[] args) {
    final Test_03_Container t = new Test_03_Container();
    final CountDownLatch latch = new CountDownLatch(1);

    new Thread(new Runnable(){
      @Override
      public void run() {
        if(t.size() != 5){
          try {
            latch.await(); // 等待门闩的开放。 不是进入等待队列
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        System.out.println("size = 5");
      }
    }).start();

    new Thread(new Runnable() {
      @Override
      public void run() {
        for(int i = 0; i < 10; i++){
          System.out.println("add Object to Container " + i);
          t.add(new Object());
          if(t.size() == 5){
            latch.countDown(); // 门闩-1
          }
          try {
            TimeUnit.SECONDS.sleep(1);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }
}

class Test_03_Container{
  List<Object> container = new ArrayList<>();

  public void add(Object o){
    this.container.add(o);
  }
  public int size(){
    return this.container.size();
  }
}