java 并发API提供了CountDownLatch类,它是一个同步辅助类。在完成一组正在其它线程中执行的操作之
前,它允许线程一直等等。这个类使用一个整数进行初始化,这个整数就是线程要等等完成的操作的数目。
当一个线程要等待某些操作先执行完成时,需要调用await()方法,这个方法让线程进入休眠直到等待的所有
操作都完成。当某一个操作完成,它将调用cuntDown()方法将CountDownLatch类内部计数器减1。当计数
器变成0的时候,CountDownLatch类将唤醒所有调用await()方法而进入休眠的线程。
CountDownLatch 对象的内部计数器被初始化之后就不能被再次初始化或者修改。
一旦计数器被初始化后,唯一能改变参数值的方法是countDown(),当计数器到达0
时,所有因调用await()方法而等待的线程立即被唤醒,再执行countDown()将不起作用。
/**
* 视频会议,当所有参与者都到齐才开始
*/
static class VideoConference implements Runnable {
private final CountDownLatch controller;
public VideoConference(int number) {
this.controller = new CountDownLatch(number);
}
//每一个参与者到场时,这个方法将被调用
public void arrive(String people) {
this.controller.countDown();
System.out.println(people + "到了,还差" + this.controller.getCount() + "位。");
}
@Override
public void run() {
System.out.println("这次会议共" + this.controller.getCount() + "人参加");
try {
controller.await();
System.out.println("会议开始了...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 参与者
*/
static class People implements Runnable {
private final String name;
private final VideoConference videoConference;
public People(String name, VideoConference videoConference) {
this.name = name;
this.videoConference = videoConference;
}
@Override
public void run() {
long duration = (long) (Math.random() * 10);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.videoConference.arrive(this.name);
}
}
public static void main(String[] args) {
VideoConference videoConference = new VideoConference(5);
new Thread(videoConference).start();
Stream.of("张三", "李四", "王五", "陈六", "赵七").forEach(name -> {
new Thread(new People(name, videoConference)).start();
});
}
这次会议共5人参加
李四到了,还差4位。
赵七到了,还差3位。
陈六到了,还差2位。
张三到了,还差1位。
王五到了,还差0位。
会议开始了...
《摘自 java7并发编程实战》