概念介绍:
CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值; 每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行; CountDownLatch可以看作是一个倒计数的锁存器,当计数减至0时触发特定的事件;利用这种特性,可以让主线程等待子线程的结束。
方法介绍:
* 该类主要方法有3个: * public CountDownLatch(int count) 构造方法参数指定了计数的次数 * public void countDown() :当前线程调用此方法,则计数减一(任务B调用) * public void await() throws InterruptedException :调用此方法会一直阻塞当前线程,直到计时器的值为0(任务A调用)
使用讲解:
要求:有一个任务A想要往下执行,但必须要等到任务B执行完毕后才可以继续往下执行。 * 让任务A调用CountDownLatch对象的await()方法, * 任务B执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法, * 这个调用await()方法的任务A将一直阻塞等待 * 直到这个CountDownLatch对象的计数值减到0为止,即任务B执行完毕。
实例讲解:
题目:假设某公司需召开一个视频会议,共有10名高管参会,只有所有高管均到场后会试才开始。请使用CountDownLatch(包: java.util.concurrent)编写一个示例模 拟上述情景。
分析:对应到当前题目,任务A:开启视频会议 任务B:10位高管到齐
代码实现:
package xmcc.mp_apidemo.test;
import java.util.concurrent.CountDownLatch;
//任务A的线程,一个线程做一个任务
public class Meet implements Runnable{
//提供一个CountDownLatch对象,用来保证任务A和任务B使用的对象是同一个。
private final CountDownLatch controller;
//有参构造,初始化CountDownLatch对象
public Meet(int number) {
//初始化计数器为10,因为有10个高管
controller = new CountDownLatch(number);
}
//提供一个方法:即任务B的具体实现,某一个高管到达
public void arrive(String name) {
System.out.println(name + " 到达会议室");
//每达到一位高管,计数器 减1
controller.countDown();
}
/**
* Runnable是一个线程类,java中常用线程之一
* 使用方法:实现Runnable接口,重写它的run()方法
* 在run()方法里,写线程需要执行的方法。
* 在其他实体类中,start()开启该线程,就会执行run()方法
*/
//这个线程实现-》开始会议,即任务A,只要去调用CountDownLatch对象的await()方法即可。
@Override
public void run() {
System.out.println("会议开启需要 : "
+ controller.getCount() + " 名高管");
try {
controller.await();
System.out.println("所有高管到达会议");
System.out.println("会议开始");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//任务B的线程
class Participant implements Runnable{
//之所以需要注入Meet对象,是为了保证两个任务使用的CountDownLatch对象是同一个。
private Meet conference;
private String name;
public Participant(Meet conference, String name) {
this.conference = conference;
this.name = name;
}
//该线程用于--》任务B的具体实现
@Override
public void run() {
try {
Thread.sleep(50);//线程休眠
//某一个高管达到会议室,去调用对应的方法,计数器的值 -1
conference.arrive(name);
}catch (InterruptedException e){
e.printStackTrace();
}
}
//主函数,用于任务A、B的整合
public static void main(String[] args) {
//创建任务A的对象,并利用其有参构造,初始化CountDownLatch对象,赋值 定时器的值为10
Meet conference = new Meet(10);
//开启任务A的线程,根据CountDownLatch对象await()的属性,任务A需要等待任务B执行完毕(即计数器的值=0的时候)
new Thread(conference).start();
//有10位高管,循环开启10个线程,去模拟高管的到场
for(int i=0;i<10;i++) {
//创建任务B的对象,10个高管,每次创建一个,模拟某一个高管的到场
Participant p = new Participant(conference, "高管 " + i);
//开启任务B的线程,执行对应的run()方法,计算器 -1
new Thread(p).start();
}
}
}
运行结果展示:
会议开启需要 : 10 名高管 高管 0 到达会议室 高管 9 到达会议室 高管 6 到达会议室 高管 7 到达会议室 高管 8 到达会议室 高管 5 到达会议室 高管 3 到达会议室 高管 4 到达会议室 高管 2 到达会议室 高管 1 到达会议室 所有高管到达会议 会议开始