java 并发API提供了CountDownLatch类,它是一个同步辅助类。在完成一组正在其它线程中执行的操做之
前,它容许线程一直等等。这个类使用一个整数进行初始化,这个整数就是线程要等等完成的操做的数目。
当一个线程要等待某些操做先执行完成时,须要调用await()方法,这个方法让线程进入休眠直到等待的全部
操做都完成。当某一个操做完成,它将调用cuntDown()方法将CountDownLatch类内部计数器减1。当计数
器变成0的时候,CountDownLatch类将唤醒全部调用await()方法而进入休眠的线程。java
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并发编程实战》dom