简介
CountDownLatch,是一个同步器,允许一个或多个线程等待,直到一组操作在其他线程中完成。
概述
初始CountDownLatch时,会给定count,await方法会阻塞,直到count减小到0,countDown方法会是count减1,count不能被重置。
应用
例一
描述
有1个老板,雇了10工人,工人就位后,并不是立即工作,而是等到老板发出指令,才会开始工作,每个工人完成工作后,也会发出一个指令反馈完成此工作,而老板会等待所有的工人都完成工作,然后做下一步打算。
代码
1 public class Driver { 2 private static final int N = 10; 3 4 public static void main(String[] args) throws InterruptedException { 5 CountDownLatch startSignal = new CountDownLatch(1); 6 CountDownLatch doneSignal = new CountDownLatch(N); 7 8 for (int i = 0; i < N; ++i) 9 new Thread(new Worker("[工人" + i + "]", startSignal, doneSignal)).start(); // 启动工作线程 10 11 System.out.println("[老板]发出开始信号"); 12 startSignal.countDown(); // 发出开始信号 13 doneSignal.await(); // 等待工人们完成 14 System.out.println("[老板]收到所有工人完成的信号"); 15 } 16 } 17 18 class Worker implements Runnable { 19 private final String name; 20 private final CountDownLatch startSignal; 21 private final CountDownLatch doneSignal; 22 23 Worker(String name, CountDownLatch startSignal, CountDownLatch doneSignal) { 24 this.name = name; 25 this.startSignal = startSignal; 26 this.doneSignal = doneSignal; 27 } 28 29 public void run() { 30 try { 31 startSignal.await(); // 工人们在此等待老板的开工信号 32 System.out.println(this.name + " >> 开始工作"); 33 doWork(); // 开始做工作 34 System.out.println(this.name + " << 完成工作"); 35 doneSignal.countDown(); // 发出完成信号 36 } catch (InterruptedException ex) { 37 } 38 } 39 40 void doWork() { 41 System.out.println(this.name + " == 正在工作"); 42 } 43 }
输出
[老板]发出开始信号 [工人0] >> 开始工作 [工人0] == 正在工作 [工人0] << 完成工作 [工人2] >> 开始工作 [工人2] == 正在工作 [工人2] << 完成工作 [工人1] >> 开始工作 [工人1] == 正在工作 [工人1] << 完成工作 [工人4] >> 开始工作 [工人3] >> 开始工作 [工人3] == 正在工作 [工人3] << 完成工作 [工人4] == 正在工作 [工人4] << 完成工作 [工人7] >> 开始工作 [工人6] >> 开始工作 [工人5] >> 开始工作 [工人5] == 正在工作 [工人5] << 完成工作 [工人6] == 正在工作 [工人7] == 正在工作 [工人6] << 完成工作 [工人7] << 完成工作 [工人8] >> 开始工作 [工人8] == 正在工作 [工人8] << 完成工作 [工人9] >> 开始工作 [工人9] == 正在工作 [工人9] << 完成工作 [老板]收到所有工人完成的信号
例二
描述
有1个很大的任务,可以分成10个子任务,交给10个线程去工作,并在最后汇总结果。
代码
1 public class Driver2 { 2 private static final int N = 10; 3 4 public static void main(String[] args) throws InterruptedException { 5 CountDownLatch startSignal = new CountDownLatch(1); 6 CountDownLatch doneSignal = new CountDownLatch(N); 7 ExecutorService e = Executors.newFixedThreadPool(N); 8 9 for (int i = 0; i < N; ++i) 10 e.execute(new WorkerRunnable(startSignal, doneSignal, i)); 11 12 e.shutdown(); 13 System.out.println("[总任务]分成" + N + "子任务并开始执行"); 14 startSignal.countDown(); // 发出开始信号 15 doneSignal.await(); 16 System.out.println("[总任务]已经完成"); 17 } 18 } 19 20 class WorkerRunnable implements Runnable { 21 private final CountDownLatch startSignal; 22 private final CountDownLatch doneSignal; 23 private final int i; 24 25 WorkerRunnable(CountDownLatch startSignal, CountDownLatch doneSignal, int i) { 26 this.startSignal = startSignal; 27 this.doneSignal = doneSignal; 28 this.i = i; 29 } 30 31 public void run() { 32 try { 33 startSignal.await(); 34 } catch (InterruptedException e) { 35 } 36 System.out.println("[子任务" + i + "]>>开始执行"); 37 doWork(i); 38 doneSignal.countDown(); 39 System.out.println("[子任务" + i + "]==已经完成"); 40 } 41 42 void doWork(int i) { 43 System.out.println("[子任务" + i + "]==正在执行"); 44 } 45 }
输出
[总任务]分成10子任务并开始执行 [子任务1]>>开始执行 [子任务1]==正在执行 [子任务1]==已经完成 [子任务4]>>开始执行 [子任务4]==正在执行 [子任务4]==已经完成 [子任务3]>>开始执行 [子任务3]==正在执行 [子任务3]==已经完成 [子任务0]>>开始执行 [子任务0]==正在执行 [子任务0]==已经完成 [子任务6]>>开始执行 [子任务6]==正在执行 [子任务6]==已经完成 [子任务2]>>开始执行 [子任务2]==正在执行 [子任务2]==已经完成 [子任务5]>>开始执行 [子任务5]==正在执行 [子任务5]==已经完成 [子任务7]>>开始执行 [子任务8]>>开始执行 [子任务9]>>开始执行 [子任务7]==正在执行 [子任务9]==正在执行 [子任务8]==正在执行 [子任务9]==已经完成 [子任务7]==已经完成 [子任务8]==已经完成 [总任务]已经完成
源码分析
尊重他人的劳动,转载请注明出处:http://www.cnblogs.com/aniao/p/aniao_cdl.html