CountDownLatch是 JDK 提供的并发流程控制的工具类,它是在 java.util.concurrent 包下,在 JDK1.5 以后加入的。
CountDownLatch
它是 JDK 提供的并发流程控制的工具类,它是在 java.util.concurrent 包下
最开始 CountDownLatch 设置的初始值为 3,然后 T0 线程上来就调用 await 方法,它的作用是让这个线程开始等待,等待后面的 T1、T2、T3,它们每一次调用 countDown 方法,3 这个数值就会减 1,也就是从 3 减到 2,从 2 减到 1,从 1 减到 0,一旦减到 0 之后,这个 T0 就相当于达到了自己触发继续运行的条件,于是它就恢复运行了。
主要方法
- 它的构造函数需要传入一个参数,该参数 count 是需要倒数的数值。
await()
:调用await()方法的线程开始等待,直到count值为0的时候才会继续执行。- await()有一个重载的方法,里面会传入超时参数,如果超时就不再等待了。
countDown()
:把数值倒数 1,也就是将 count 值减 1,直到减为 0 时,且之前等待的线程会被唤起。
用法
场景一
一个线程等待其他多个线程都执行完毕,再继续自己的工作。比如在比赛跑步时有5个运动员参赛,终点有一个裁判员,当所有人都跑到终点之后,相当于裁判员等待5个运动员都跑到终点,宣布比赛结束。
public class RunDemo1 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(5);
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int no = i //新建任务
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep((long) (Math.random() * 10000));
System.out.println 运动员完成了比赛。");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
}
//提交任务
service.submit(runnable);
}
System.out.println("等待5个运动员都跑完.....");
//调用await让主线程开始等待子线程执行完毕
latch.await();
System.out.println("所有人都跑完了,比赛结束。");
}
}
我们新建了一个初始值为 5 的 CountDownLatch,然后建立了一个固定 5 线程的线程池,用一个 for 循环往这个线程池中提交 5 个任务,每个任务代表一个运动员,这个运动员会首先随机等待一段时间,代表他在跑步,然后打印出他完成了比赛,在跑完了之后,同样会调用 countDown 方法来把计数减 1。
场景二
多个线程等待某一个线程的信号,同时开始执行。比如在运动员起跑之前都会等待裁判员发号施令,一声令下运动员统一起跑。
public class RunDemo2 {
public static void main(String[] args) throws InterruptedException {
System.out.println("运动员有5秒的准备时间");
CountDownLatch countDownLatch = new CountDownLatch(1);
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
final int no = i + 1;
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println( "号运动员准备完毕,等待裁判员的发令枪");
try //五个线程都会进入等待状态
countDownLatch.await();
System.out.println(no + "号运动员开始跑步了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
service.submit(runnable);
}
Thread.sleep(5000);
System.out.println("5秒准备时间已过,发令枪响,比赛开始!" //调用countDown之后才会将五个等待的线程唤 然后线程执行await()方法之后的逻辑
countDownLatch.countDown();
}
}