一、场景
班里有七名同学,放学后,七名同学走完,班长关门走人。
二、普通方法public class CountDownLatchDemo {
public static void main(String[] args) {
for (int i=0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t上完自习,离开教室");
}, String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName() + "\t **************班长最后关门走人");
}
}
班长,先关门走人了??把他们都锁班级里了?
三、CountDownLatch 3.1 概念让一些线程阻塞,直到另外一些完成后才被唤醒。
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞,其他线程调用countDown方法,计数器减1(调用countDown方法时线程不会阻塞),当计数器的值变为0,因调用await方法被阻塞的线程会被唤醒,继续执行
countDownLatch这个类,使一个线程等待其他线程各自执行完毕后再执行
是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就减1,当计数器的值为0时,表示所有线程都执行完毕,然后,再闭锁上等待的线程就可以恢复工作了
3.2 源码countDownLatch类中只提供了一个构造器:
//参数count为计数值
public CountDownLatch(int count) { };
类中有三个方法是最重要的:
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException { };
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
//将count值减1
public void countDown() { };
3.2 关门问题
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6); //设置班级同学总数为6
for (int i=0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t上完自习,离开教室");
countDownLatch.countDown(); //班级同学走一个减一个1
}, String.valueOf(i)).start();
}
countDownLatch.await(); //上面的走完,我下面的主线程才能走,控制前面的任务完成以后,才能进行后面的任务
System.out.println(Thread.currentThread().getName() + "\t **************班长最后关门走人");
}
}
成功解决上述问题
3.3 秦灭六国问题public enum CountryEnum {
ONE(1, "齐"),
TWO(2, "楚"),
THREE(3, "燕"),
FOUR(4, "赵"),
FIVE(5, "魏"),
SIX(6, "韩");
@Getter
private Integer retCode;
@Getter
private String retMessage;
CountryEnum(Integer retCode, String retMessage) {
this.retCode = retCode;
this.retMessage = retMessage;
}
public static CountryEnum forEach_CountryEnmu(int index) {
CountryEnum[] enums = CountryEnum.values();
for (CountryEnum countryEnum : enums) {
if (index == countryEnum.getRetCode()) {
return countryEnum;
}
}
return null;
}
}
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i=1; i {
System.out.println(Thread.currentThread().getName() + "\t 国,被灭");
countDownLatch.countDown();
}, CountryEnum.forEach_CountryEnmu(i).getRetMessage()).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + "\t *******************秦帝国,一统华夏");
}
public static void closeDoor(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6); //设置班级同学总数为6
for (int i=0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t上完自习,离开教室");
countDownLatch.countDown(); //班级同学走一个减一个1
}, String.valueOf(i)).start();
}
countDownLatch.await(); //上面的走完,我下面的主线程才能走,控制前面的任务完成以后,才能进行后面的任务
System.out.println(Thread.currentThread().getName() + "\t **************班长最后关门走人");
}
}
参考,视频教程