java并发(四)CountDownLatch闭锁

时间:2021-06-20 20:51:19

CountDownLatch

  1. Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器
    的性能。
  2. CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作
    之前,它允许一个或多个线程一直等待。
  3. 闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活
    动直到其他活动都完成才继续执行:
    • 确保某个计算在其需要的所有资源都被初始化之后才继续执行;
    • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;
    • 等待直到某个操作所有参与者都准备就绪再继续执行。

类似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

可见打印输出了执行时间