首先,一定要注意一点,就是调用countDown()方法时,必须放到finally执行,否则会发生永远阻塞。

  1. public class CountDownLathTest {
  2. public static void main(String[] args) {
  3. CountDownLatch countDownLatch = new CountDownLatch(3);
  4. IntStream.range(0,3).forEach(i -> new Thread(()->{
  5. try {
  6. Thread.sleep(2000);
  7. System.out.println("hello");
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }finally {
  11. countDownLatch.countDown();
  12. }
  13. }).start());
  14. System.out.println("主线程运行");
  15. try {
  16. countDownLatch.await();
  17. System.out.println("所有线程执行完毕");
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }

await源码

  1. public void await() throws InterruptedException {
  2. // 这个1实际上只是为了AQS执行,并无实际意义
  3. sync.acquireSharedInterruptibly(1);
  4. }
  5. public final void acquireSharedInterruptibly(int arg)
  6. throws InterruptedException {
  7. if (Thread.interrupted())
  8. throw new InterruptedException();
  9. if (tryAcquireShared(arg) < 0)
  10. // 执行后续线程代码
  11. doAcquireSharedInterruptibly(arg);
  12. }
  13. // 获取计数
  14. protected int tryAcquireShared(int acquires) {
  15. return (getState() == 0) ? 1 : -1;
  16. }

countDown源码

  1. public void countDown() {
  2. sync.releaseShared(1);
  3. }
  4. public final boolean releaseShared(int arg) {
  5. if (tryReleaseShared(arg)) {
  6. // 唤醒线程
  7. doReleaseShared();
  8. return true;
  9. }
  10. return false;
  11. }
  12. protected boolean tryReleaseShared(int releases) {
  13. // 将计数器的值每次减一,当值归零后发出信号
  14. for (;;) {
  15. // 获取计数器的值
  16. int c = getState();
  17. // 计数器的值归零后直接返回
  18. if (c == 0)
  19. return false;
  20. // CAS处理,减一
  21. int nextc = c-1;
  22. if (compareAndSetState(c, nextc))
  23. // 经过减一后,nextc才会变为0
  24. return nextc == 0;
  25. }
  26. }