CountDownLatch一个同步辅助工具,允许一个或多个线程等待其他线程中执行的一组操作完成。类似的场景有考试,比如老师必须要等学生交完试卷才能离开考场
代码案例
public class Exam {
public static void main(String[] args) throws InterruptedException {
//学生人数
int studentNum = 50;
//完成标记
CountDownLatch doneSignal = new CountDownLatch(studentNum);
//开始标记,用于一开始学生必须等待老师发放试卷,才能答题后交卷
CountDownLatch startSignal = new CountDownLatch(1);
new Thread(() -> {
try {
//假设学生先来
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//业务原子性,不然打印会乱序
synchronized (startSignal) {
startSignal.countDown();
System.out.println(Thread.currentThread().getName() + ": " + "考试开始,发放试卷,学生开始答题!");
}
try {
doneSignal.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("考试结束,学生已经全部交卷");
}, "Teacher").start();
new Thread(() -> {
//生成50个线程,每个线程代表一个学生,
for (int num = 1; num <= studentNum; num++) {
new Thread(() -> {
try {
startSignal.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//业务原子性,不然打印会乱序
synchronized (startSignal) {
doneSignal.countDown();
System.out.println(Thread.currentThread().getName() + ": " + "交卷");
}
}, "Student-" + num).start();
}
}).start();
}
}
这里需要注意的是为什么要用两CountDownLatch配合使用,代码里面的stratSingal的作用是学生必须要等老师发放了试卷才能答题交卷,如果注释了的话,就有可能是学生先交试卷,老师后发放试卷.在main线程中 这两个线程的执行顺序不一定是前后顺序,当然老师和学生都有可能先来到考场