《Java源码分析》:CountDownLatch
Latch:闭锁。
有人把Latch比喻成是一个门,在门打开之前,所有想进门的线程都被阻塞,在门打开之后,所有想进门的线程全部通过,且门打开之后就不能再关闭。
CountDownLatch是一个同步辅助类,允许一个或多个线程等待直到其它线程的一些操作已经准备完成。
CountDownLatch是JDK 5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生。CountDownLatch有一个正数计数器,countDown方法对计数器做减操作,await方法等待计数器达到0。所有await的线程都会阻塞直到计数器为0或者等待线程中断或者超时。
即CountDownLatch里面有一个计数器,当计数器不为零时所有线程一直阻塞。当计数器为零时,则所有等待此门的线程就全部唤醒开始工作。
下面这个例子就很好的介绍了CountDownLatch的含义和用法。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
运行结果:
main为所有的线程的运行做准备。。。。
main线程awaiting....
Thread-0 is running...
Thread-2 is running...
Thread-4 is running...
Thread-6 is running...
Thread-8 is running...
Thread-1 is running...
Thread-3 is running...
Thread-5 is running...
Thread-7 is running...
Thread-9 is running...
main线程又开始运行
main线程运行结束
源码分析
首先看下CountDownLa的构造函数,构造函数需要传入一个大于的零的数。
从构造函数中可以看到,CountDownLatch类是直接委托给实现了AQS类的内部类Sync类实现的。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
分析await()方法的内部实现
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
调用countDown方法的内部实现
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
由于里面的代码逻辑和前面博文中介绍Semaphore类、ReentrantLock基本一致,这里就不再介绍。
小结
只需要记住:CountDownLatch是一个同步辅助类,当CountDownLatch类中的计数器减少为零之前所有调用await方法的线程都会被阻塞,如果计数器减少为零,则所有线程被唤醒继续运行。
一般的应用场景为:
1、其它的一些线程需要某个线程做准备工作。例如:数据库的连接等。
2、某个线程需要等待一些线程工作完之后清理资源。断开数据库的连接等。