CountDownLatch是基于AQS的操作共享锁的表现,可以控制多个线程,一起执行。模仿并发
CountDownLatch类中有2个方法。1. await();表示线程阻塞,
2. countDown();表示,计数器减一。在线程阻塞后,计数器减至0后才可以唤醒阻塞的线程。
场景一:模仿高并发,多个线程,同事访问一个资源。
代码:
package com.example.demo2.cusdemo.countdowndemo;
import java.util.concurrent.CountDownLatch;
/**
* @Author wfl 2022/1/28
* 功能
*/
public class TestCountDowm {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(1);
for (int i = 0; i < 5; i++) {
int finalI = i;
new Thread(() -> {
//所有的线程启动完成先在这阻塞
try {
Thread.sleep(1000 * finalI);
//下面注释,放开再执行结果不一样
// latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("现在时间是---" + Thread.currentThread().getName() + "---" + System.currentTimeMillis());
}, "thread" + i).start();
}
System.out.println("主线程启动完成--" + System.currentTimeMillis());
try {
Thread.sleep(6000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
//为上边所有的线程放行
latch.countDown();
System.out.println("主线程运行完成--" + System.currentTimeMillis());
}
}
执行结果1,注释代码latch.await();
执行结果2,放开注释代码。并发执行
场景二:多个线程完成自己的任务,有一个线程进行汇总。
比如:每个班各自统计自己的学生数量,都统计完成后,在有一个线程汇总学生数量。
代码
package com.example.demo2.cusdemo.countdowndemo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* @Author wfl 2022/1/28
* 功能
*/
public class TestCountDowm2 {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(5);
List<Integer> list = countStudentQuantity(latch);
System.out.println("主线程启动完成--" + System.currentTimeMillis());
// try {
// //等待所有的线程都统计完这里才放行
// latch.await();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("子线程统计各班学生总数完成完成--" + System.currentTimeMillis());
int stuSum = 0;
for (Integer stu : list) {
stuSum +=stu;
}
System.out.println("主线程运行完成--" + System.currentTimeMillis());
System.out.println("统计学生总数--" + stuSum);
}
private static List<Integer> countStudentQuantity(CountDownLatch latch) {
List<Integer> list = new ArrayList<>(8);
for (int i = 0; i < 5; i++) {
int finalI = i+1;
new Thread(() -> {
//所有的线程启动完成先在这阻塞
try {
// 各班统计时间不一样
Thread.sleep(1000 * finalI);
//各班统计学生数量
int stu = finalI *100;
System.out.println(finalI+"班学生" + Thread.currentThread().getName() + "---" + stu);
//放到集合
list.add(stu);
// 每个班统计完成,这里都需要countDown一次,总共5次后主线程就不会阻塞
// latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "thread" + finalI).start();
}
return list;
}
}
执行结果1;
执行结果2;放开注释代码,共2处