一、总论:在JDK中提供了几种并发工具类
  1)CountDownLatch(同步倒数计数器:等待多线程(或者多步骤)完成)
  2)CyclicBarrier(循环屏障:同步屏障)
  3)Semaphore(信号量:控制并发进程数)
  主要参考资料:java并发编程的艺术、Java并发——同步工具类
  二、CountDownLatch(同步倒数计数器)–不仅仅用于多线程
  1.作用:允许一个或多个线程等待其他线程完成操作。
  CountDownLatch的构造函数接受一个int类的参数作为计数器,如果你想等待N个节点完成,那这里传入N.
  2.countDown方法:当我们调用CountDownLatch的countDown方法时,N会减1;CountdownLatch的await方法会阻塞当前线程,直到N变成零。
  3.使用说明:由于CountDown可以用在任何地方,所以这里说的N个点,可以是N个线程,也可以说是N个步骤。
  4.await方法:明确一点,countDown方法是目标线程或步骤调用的,用来通知监控线程自己的任务完成;await方法是当前线程或者主干步骤调用的,用来监控整个线程或步骤的运行状态,另外await方法一般都会伴有超时等待的await方法,这个方法在等待指定的时间后,不会在阻塞当前线程,而是继续线程。
  5.常用API
  1)构造方法
  CountDownLatch(int count): 构造方法参数指定了计数的次数。
  2)void await():使当前线程在锁存计数器在到零之前一直阻塞等待,除非线程被中断。
  3)boolean await(long timeout,TimeUnit timeUnit):使当前线程在锁存计数器在到零之前一直阻塞等待,除非线程被中断或者超出了指定等待的超时时间。
  4)void countDown() 计数减1。当计数为0,则释放所有等待的线程。
  5) long getCount() 返回当前计数。
  6) String toString() 返回标识此锁存器及其状态的字符串
  三、一个小小例子
  唐僧监工三个徒弟去斩妖除魔,等到每个徒弟都打败妖怪;九九八十难才过去一难!
  package multiTask.bean.countDownLatch;
  import java.util.concurrent.*;
  /**
  * Created by zyl on 2016/12/4.
  */
  public class CountDownLatchDemo {
  public static void main(String[] arg) throws InterruptedException {
  System.out.println("current thread ..." + Thread.currentThread().getName());
  CountDownLatch count = new CountDownLatch(3);
  ExecutorService executorService = Executors.newCachedThreadPool();
  executorService.execute(new Worker(count, "悟空"));
  executorService.execute(new Worker(count, "八戒"));
  executorService.execute(new Worker(count, "沙僧"));
  new Boss(count, "唐僧").awaitForWorkerDone();
  System.out.println("所有事情都做完了,唐僧很满意!");
  executorService.shutdown();
  }
  static class Boss {
  private CountDownLatch count;
  private String bossName;
  public Boss(CountDownLatch count, String bossName) {
  this.bossName = bossName;
  this.count = count;
  }
  public void awaitForWorkerDone() throws InterruptedException {
  this.count.await();
  System.out.println("Boss monitor is done.");
  }
  }
  static class Worker implements Runnable {
  private CountDownLatch count;
  private String workerName;
  public Worker(CountDownLatch count, String workerName) {
  this.count = count;
  this.workerName = workerName;
  }
  @Override
  public void run() {
  System.out.println(workerName + " " + Thread.currentThread().getName() + " is running ..");
  try {
  Thread.sleep(3000);
  } catch (InterruptedException e) {
  e.printStackTrace();
  }
  /*
  * 完成任务,锁存计数减1*
  * */
  this.count.countDown();
  }
  }
  }