Java 多线程 系列文章目录:
- Java 多线程(一)线程间的互斥和同步通信
- Java 多线程(二)同步线程分组问题
- Java 多线程(三)线程池入门 Callable 和 Future
- Java 多线程(四)ThreadPoolExecutor 线程池各参数的意义
- Java 多线程(五)Lock 和 Condition 实现线程同步通信
- Java 多线程(六)Semaphore 实现信号灯
- Java 多线程(七)CyclicBarrier 同步的工具类
- Java 多线程(八)CountDownLatch 同步工具类
- Java 多线程(九)Exchanger 同步工具类
- Java 多线程(十)ArrayBlockingQueue 阻塞队列
- Java 多线程(十一)JDK 同步集合
CountDownLatch 是一个同步工具类,用于让一个或多个线程处于等待状态,直到一系列的操作在其他线程执行完毕后。
案例1:主线程等待,直到 3 个线程都执行完毕之后才执行
public class CountDownLatchTest1 {
private static CountDownLatch countDownLatch = new CountDownLatch(3);
public static void main(String[] args) throws InterruptedException {
doSomething();
doSomething();
doSomething();
System.out.println("主线程开始等待...");
countDownLatch.await();
System.out.println("主线程开始执行了...");
}
private static void doSomething() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 执行操作需要 3s");
countDownLatch.countDown();
}
}).start();
}
}
执行结果如下所示:
主线程开始等待...
Thread-1 执行操作需要 3s
Thread-0 执行操作需要 3s
Thread-2 执行操作需要 3s
主线程开始执行了...
接下来,我们再来看一个复杂一点的例子。
案例2:可以将下面的程序理解成:一个裁判和三个运动员之间的关系,比赛之前,裁判在等待运动员就绪,裁判鸣枪后,运动员开始跑,只有等到三个运动员都跑完了,才能宣布成绩。可以用如下程序来实现:
public class CountdownLatchTest2 {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
// 一个裁判
final CountDownLatch cdOrder = new CountDownLatch(1);
// 三个运动员
final CountDownLatch cdAnswer = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
Runnable runnable = new Runnable() {
public void run() {
try {
System.out.println("线程" + Thread.currentThread().getName() + "正准备接受命令");
//直到 cdOrder 的计数器归0,才能往下执行
cdOrder.await();
//如果把这个程序比喻成一个3个运动员在比赛,还有一个裁判
//cdOrder的计数器归0,表明裁判鸣枪了,运动员可以跑了.
System.out.println("线程" + Thread.currentThread().getName() + "已接受命令");
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程" + Thread.currentThread().getName() + "回应命令处理结果");
//每一个运动员到此计数器就减一
cdAnswer.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
try {
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程" + Thread.currentThread().getName() + "即将发布命令");
// cdOrder 的计数器减1,
cdOrder.countDown();
System.out.println("线程" + Thread.currentThread().getName() + "已发送命令,正在等待结果");
// cdAnswer 直到计数器为 0,也就是上面三个线程执行完毕
cdAnswer.await();
//裁判就可以公布成绩了
System.out.println("线程" + Thread.currentThread().getName() + "已收到所有响应结果");
} catch (Exception e) {
e.printStackTrace();
}
service.shutdown();
}
}
执行结果如下: