Case:假如一个页面要请求的数据很多,需要分开请求各个小模块的数据,只有当所有的请求都完成后,才能执行下一步任务。
先写一个白纸一样的代码
public class CountDownLatchDemo {
public static void main(String[] args) {
for (int i = 1; i <= 6; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程:\t"+Thread.currentThread().getName()+"\t 执行完毕");
}
},String.valueOf(i)).start();
}
System.out.println("所有的线程都执行完毕,进入下一个环接!!!");
}
}
---打印结果-----
线程: 2 执行完毕
所有的线程都执行完毕,进入下一个环接!!!
线程: 3 执行完毕
线程: 1 执行完毕
线程: 5 执行完毕
线程: 6 执行完毕
线程: 4 执行完毕
才执行完一个请求,就直接说进入下一个环接了... ...失败
然后启用CountDownLatch...
public class CountDownLatchDemo {
public static void main(String[] args) {
int count = 6;
final CountDownLatch countDownLatch = new CountDownLatch(count);
for (int i = 1; i <= count; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程:\t"+Thread.currentThread().getName()+"\t 执行完毕");
countDownLatch.countDown();
}
},String.valueOf(i)).start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("所有的线程都执行完毕,进入下一个环接!!!");
}
}
---打印结果------
线程: 1 执行完毕
线程: 2 执行完毕
线程: 3 执行完毕
线程: 4 执行完毕
线程: 6 执行完毕
线程: 5 执行完毕
所有的线程都执行完毕,进入下一个环接!!!
完美~
em......感觉就写这么个“线程 x 执行完毕”没啥意思,再搞点有意思的......
Case...Update:简单模拟一个秦灭六国,一统天下的情景
public class CountDownLatchDemo {
public static void main(String[] args) {
int count = 6;
final CountDownLatch downLatch = new CountDownLatch(6);
for (int i = 1; i <=count; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("大秦灭掉了\t"+Thread.currentThread().getName()+"\t!");
downLatch.countDown();
}
},getCountryName(i)).start();
}
try {
downLatch.await();
System.out.println("大秦已灭六国,一统天下!!!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static String getCountryName(int i) {
if (i == 1){
return "韩国";
}else if (i == 2){
return "赵国";
}else if (i == 3){
return "魏国";
}else if (i == 4){
return "楚国";
}else if (i == 5){
return "燕国";
}else if (i == 6){
return "齐国";
}
return "某国";
}
}
---打印结果-------
大秦灭掉了 韩国 !
大秦灭掉了 齐国 !
大秦灭掉了 燕国 !
大秦灭掉了 楚国 !
大秦灭掉了 魏国 !
大秦灭掉了 赵国 !
大秦已灭六国,一统天下!!!
完美.......中有那么一丢丢瑕疵......
因为其中涉及到的国家的名字是通过if ... else ...的方式一个一个比对出来的,如果是前几个比对成功还好,如果是最后一次才比对成功,那要比6次,这才6个,要是排列水浒108将.......最坏要比107次......如果比对的是全球的国家呢.......阔怕,咋整?
Case—Update—Again:不要用if...else...
public enum CountryEnum {
ONE(1,"韩国"),TWO(2,"赵国"),THREE(3,"魏国"),FOUR(4,"楚国"),FIVE(5,"燕国"),SIX(6,"齐国");
int index;
String name;
CountryEnum(int index, String name) {
this.index = index;
this.name = name;
}
public static String getCountryName(int i){
CountryEnum[] array = CountryEnum.values();
for (CountryEnum countryEnum : array) {
if (i ==countryEnum.index) return countryEnum.name;
}
return "某国";
}
}
public class CountDownLatchDemo {
public static void main(String[] args) {
int count = 6;
final CountDownLatch downLatch = new CountDownLatch(6);
for (int i = 1; i <=count; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("大秦灭掉了\t"+Thread.currentThread().getName()+"\t!");
downLatch.countDown();
}
},CountryEnum.getCountryName(i)).start();
}
try {
downLatch.await();
System.out.println("大秦已灭六国,一统天下!!!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- -- - - - - -
大秦灭掉了 韩国 !
大秦灭掉了 赵国 !
大秦灭掉了 魏国 !
大秦灭掉了 燕国 !
大秦灭掉了 齐国 !
大秦灭掉了 楚国 !
大秦已灭六国,一统天下!!!
这里用了枚举类,主要是枚举的这种使用方式ONE(1,value1,value2,...),就相当于一个数据库表一样。
最后再来介绍这篇的主咖:CountDownLatch
- 它让一些线程阻塞,直到另一些线程完成一系列操作后才被唤醒
- 主要有两个方法,当一个或多个线程调用 await 方法时调用线程会被阻塞,其他线程调用 countDown 方法会将计数器减1,当计数器数值变为 0 时,之前调用await方法被阻塞的线程就会被唤醒继续执行
可以实现这种需求的不止 CountDownLatch 一个,还有他的胞弟:CyclicBarrier