java concurrent包学习–CountDownLatch
CountDownLatch简介
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
CountDownLatch方法列表
CountDownLatch(int count)
构造一个用给定计数初始化的 CountDownLatch。
// 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
void await()
// 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
boolean await(long timeout, TimeUnit unit)
// 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
void countDown()
// 返回当前计数。
long getCount()
// 返回标识此锁存器及其状态的字符串。
String toString()
个人理解
CountDownLatch 相当于设置了一道有count个闩的门(当闩为0时 门将打开)
执行await()操作的线程都被堵在门前,等待门被打开
执行await(long timeout, TimeUnit unit)操作的线程 若指定的时间内门还未打开, 则该方法抛出异常不再等待
当执行countDown()操作时 相当于减少一个闩(count–)
当闩(count)的数量为0时(门被打开) 会唤醒所有执行await(?)操作的线程 执行后续操作
使用场景
实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。
开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。
死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。
示例代码(java 1.8)
public static void main(String[] args) {
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
int j = i;
new Thread(()->{
try {
System.out.println(String.format("runner:%s wait for begin...", j));
begin.await();
System.out.println(String.format("runner:%s begin run...", j));
long st = System.currentTimeMillis();
Thread.sleep(100+new Random().nextInt(900));
long et = System.currentTimeMillis();
System.out.println(String.format("runner:%s run over cost:%sms", j, (et-st)));
end.countDown();
} catch (Exception e) {
}
}).start();
}
try {
Thread.sleep(1000);
} catch (Exception e) {
}
System.out.println("game begin ...");
begin.countDown();
try {
//end.await(500, TimeUnit.MILLISECONDS);
end.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("game end.");
}
输出结果
runner:5 wait for begin...
runner:2 wait for begin...
runner:6 wait for begin...
runner:1 wait for begin...
runner:7 wait for begin...
runner:0 wait for begin...
runner:4 wait for begin...
runner:3 wait for begin...
runner:9 wait for begin...
runner:8 wait for begin...
game begin ...
runner:2 begin run...
runner:5 begin run...
runner:6 begin run...
runner:1 begin run...
runner:7 begin run...
runner:0 begin run...
runner:4 begin run...
runner:3 begin run...
runner:9 begin run...
runner:8 begin run...
runner:0 run over cost:133ms
runner:9 run over cost:414ms
runner:6 run over cost:437ms
runner:1 run over cost:475ms
runner:3 run over cost:551ms
runner:4 run over cost:557ms
runner:5 run over cost:566ms
runner:8 run over cost:634ms
runner:7 run over cost:662ms
runner:2 run over cost:708ms
game end.