一个关于线程并发的小知识点,写下来重新记忆一遍
我们用代码说明问题:现在用三个工人A,B,C在汽车工厂里做事,因为他们分别加工同一辆车的轮胎,引擎,和外壳,只有等他们全部加工完,才能进行组装工作!当然加工不同组件的用时肯定是不一样的!在这里设他们完成相应的工作的时间分别为:1000毫秒,2000毫秒,3000毫秒;当他们全部完成相应的零件加工工作,最后一起进行组装工作,然后下班回家!
我们先不用CountDownLatch来实现这个过程:
package countdownlatch;
public class TestCountThread {
private static int n=3;
public static void main(String[] args) {
work("A");
work("B");
work("C");
}
/**
* 启线程模拟工作
* @param str
*/
private static void work(final String str){
new Thread(){
@Override
public void run() {
super.run();
try {
if("A".equals(str)){
Thread.sleep(1000);
System.out.println(str+" 已经加工完轮胎");
}else if("B".equals(str)){
Thread.sleep(2000);
System.out.println(str+" 已经加工完引擎");
}else{
Thread.sleep(3000);
System.out.println(str+" 已经加工完外壳");
}
n--;
offDuty();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
private static synchronized void offDuty(){
if(n==0){
System.out.println("大家可以进行组装,然后下班了!");
}
}
}
结果:
A 已经加工完轮胎
B 已经加工完引擎
C 已经加工完外壳
大家可以进行组装,然后下班了!
在这里我使用了一个变量n来标记剩下未完成工作的个数,当未完成工作的个数为零时,执行组装,而且每完成一个工作,都要去检查一遍大家是否都已经完成(即调用offDuty方法);
现在使用CountDownLatch实现同样的效果
package countdownlatch;
import java.util.concurrent.CountDownLatch;
public class TestCountDownLatch {
//一个线程同步助手
private static CountDownLatch latch;
public static void main(String[] args) throws InterruptedException {
latch=new CountDownLatch(3);
work("A");
work("B");
work("C");
latch.await();
offDuty();
}
/**
* 启线程模拟工作
* @param str
*/
private static void work(final String str){
new Thread(){
@Override
public void run() {
super.run();
try {
if("A".equals(str)){
Thread.sleep(1000);
System.out.println(str+" 已经加工完轮胎");
}else if("B".equals(str)){
Thread.sleep(2000);
System.out.println(str+" 已经加工完引擎");
}else{
Thread.sleep(3000);
System.out.println(str+" 已经加工完外壳");
}
latch.countDown();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
private static void offDuty(){
System.out.println("大家可以进行组装,然后下班了!");
}
}
结果:
A 已经加工完轮胎
B 已经加工完引擎
C 已经加工完外壳
大家可以进行组装,然后下班了!
大家可以看到结果是一样的;
countDownLatch是一个同步工具类,类似于一扇门,在达到敞开状态时,任何线程都不能通过!达到敞开状态后,就一直保持敞开状态。其内部内嵌了一个计数器,构建对象时会给计算器赋值,countDown()方法会让计数器-1;当计数器为零时,CountDownLatch变为敞开状态!