CountDownLatch
- Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器
的性能。 - CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作
之前,它允许一个或多个线程一直等待。 - 闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活
动直到其他活动都完成才继续执行:- 确保某个计算在其需要的所有资源都被初始化之后才继续执行;
- 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;
- 等待直到某个操作所有参与者都准备就绪再继续执行。
类似join和yield方法
举例说明
创建一个类实现Runnable接口在run方法中打印100以内的偶数,在主方法中测试该run方法执行时间
class LatchDemo implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
if(i%2==0){
System.out.println(i);
}
}
}
}
主函数测试方法:
public static void main(String[] args) {
LatchDemo ld = new LatchDemo();
long start = System.currentTimeMillis();
for(int i=0;i<5;i++){
new Thread(ld).start();
}
long end = System.currentTimeMillis();
System.out.println("spend time:"+(end-start));//spend time:1008
}
输出结果:
spend time:1
0
0
0...
结果并不像我们所预想的那样,并没有计算出执行了多长时间,
原因分析
创建了10个子线程之的循环结束之后,主线程继续执行,主线程打印时间后结束,但是子线程还在运行。所以导致我们看到的结果。
解决方式
原因分析完毕,我们想在子线程全部执行完之后再继续执行主线程,这个时候打印的时间就有事子线程真正执行他的时间。
使用CountDownLatch闭锁
class LatchDemo implements Runnable{
private CountDownLatch latch;
public LatchDemo(CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
// 加上 catch 和 finally,在后这种保证方法必须被执行
try {
for(int i=0;i<100;i++){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i%2==0){
System.out.println(i);
}
}
} finally {
latch.countDown();//相当于--,每次执行此方法就减1技计数
}
}
}
测试主方法:
public static void main(String[] args) {
// 要控制 5 个线程,所以传入的是 5
CountDownLatch latch = new CountDownLatch(5);
LatchDemo ld = new LatchDemo(latch);
// LatchDemo ld = new LatchDemo();
long start = System.currentTimeMillis();
for(int i=0;i<5;i++){
new Thread(ld).start();
}
try {
latch.await();//主线程让出cpu执行权,释放对象锁,子线程全部执行完然后继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("spend time:"+(end-start));//spend time:1008
}
结果输出:
...
98
98
98
spend time:1009
可见打印输出了执行时间