直接上代码看,一级级的升级代码,从test1() 到test5()在main方法运行
package com.testSSM.test.utils.thread.CountDownLatch2;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class TestMain {
/**
* 模拟爸爸去饭店
*/
public static void fatherToRes() {
System.out.println("爸爸步行去饭店需要3小时。");
}
/**
* 模拟我去饭店
*/
public static void motherToRes() {
System.out.println("妈妈挤公交去饭店需要2小时。");
}
/**
* 模拟妈妈去饭店
*/
public static void meToRes() {
System.out.println("我乘地铁去饭店需要1小时。");
}
/**
* 模拟一家人到齐了
*/
public static void togetherToEat() {
System.out.println("一家人到齐了,开始吃饭");
}
public static void test1() {
fatherToRes();
motherToRes();
meToRes();
togetherToEat();
}
public static void test2() {
new Thread() {
public void run() {
fatherToRes();
};
}.start();
new Thread() {
public void run() {
motherToRes();
};
}.start();
new Thread() {
public void run() {
meToRes();
};
}.start();
togetherToEat();
}
/**
* 但是,忙等这样的代码对于CPU的消耗太巨大了,我们需要更好的实现方式。 顺便说一下volatile,为什么我们用volatile修饰 i 呢,
* 因为当多个线程操作同一个变量时, 为了保证变量修改对于其他线程的可见性,必须使用同步,volatile对于可见性的实现是个不错的选择, 但是我们代码中的
* i -- 也有可能因为并发造成一定的问题,毕竟i--不是原子操作, 正常最好使用同步块或者AtomicLong.decrementAndGet()实现--
*/
private static volatile int i = 3;
/**
* 以上两段代码,在使用Integer的时候,必须加上synchronized保证不会出现并发线程同时访问的情况,
* 而在AtomicInteger中却不用加上synchronized,在这里AtomicInteger是提供原子操作的,下面就对这进行相应的介绍。
* //private static AtomicInteger count = new AtomicInteger(3);
*/
public static void test3() {
new Thread() {
public void run() {
fatherToRes();
i--;
};
}.start();
new Thread() {
public void run() {
motherToRes();
i--;
};
}.start();
new Thread() {
public void run() {
meToRes();
i--;
};
}.start();
while (i != 0)
;// 顶住不让往下走,除非i达到预定值
togetherToEat();
}
private static CountDownLatch latch = new CountDownLatch(3);
public static void test5() throws InterruptedException {
new Thread() {
public void run() {
fatherToRes();
latch.countDown();
};
}.start();
new Thread() {
public void run() {
motherToRes();
latch.countDown();
};
}.start();
new Thread() {
public void run() {
meToRes();
latch.countDown();
};
}.start();
latch.await();
togetherToEat();
}
public static void main(String[] args) throws InterruptedException {
test5();
}
}