CountDownLatch

时间 2019/5/29 10:48:56 加载中...

介绍

Java中的concurrent包中的CountDownLatch其实可以看做一个计数器。只不过这个计数器里的操作是原子操作,同时只能一个线程去操作这个计数器。

CountDownLatch初始化的时候可以设定初始值,任一对象调用CountDownLatch对象的await()方法都会阻塞,直到其他线程调用CountDownLatch对象的countDown方法,每countDown一次,计数器减1,当计数器为0时,就不会再阻塞了。

应用场景

有一个任务要往下执行,必须等其他任务执行完毕才可以。

想要往下执行的任务调用CountDownLatch对象的await方法就会阻塞,其他任务完成后,各自调用CountDownLatch对象的countDown方法,当所有任务完成后,计数器变成0,也就不再阻塞了。

示例

有三个工人,一个老板,三个工人干完活,老板才开始检查。

我们先简单的实现部分代码

工人

  1. package ThreadDemo.CountDownLatchDemo.demo02;
  2. public class Worker implements Runnable {
  3. /*
  4. * 员工编号
  5. */
  6. private String workCode;
  7. public Worker(String workCode){
  8. this.workCode = workCode;
  9. }
  10. @Override
  11. public void run() {
  12. String msg = new StringBuilder()
  13. .append("我是员工")
  14. .append(workCode)
  15. .append(",我正在干活")
  16. .toString();
  17. System.out.println(msg);
  18. }
  19. }

老板

  1. package ThreadDemo.CountDownLatchDemo.demo02;
  2. public class Boss implements Runnable{
  3. @Override
  4. public void run() {
  5. System.out.println("我是老板,我检查了");
  6. }
  7. }

测试

  1. package ThreadDemo.CountDownLatchDemo.demo02;
  2. import java.util.concurrent.ExecutorService;
  3. import java.util.concurrent.Executors;
  4. public class Program {
  5. public static void main(String[] args) {
  6. Worker worker1 =new Worker("worker1");
  7. Worker worker2 =new Worker("worker2");
  8. Boss boss = new Boss();
  9. ExecutorService executorService = Executors.newCachedThreadPool();
  10. executorService.execute(worker1);
  11. executorService.execute(worker2);
  12. executorService.execute(boss);
  13. executorService.shutdown();
  14. System.out.println("over");
  15. }
  16. }
  17. //输出结果
  18. 我是员工worker1,我正在干活
  19. 我是员工worker2,我正在干活
  20. over
  21. 我是员工worker3,我正在干活
  22. 我是老板,我检查了

目前的情况,并没有实现 “员工干完活,老板才检查” 这个条件。
现在我们通过 CountDownLatch 来实现这个功能。

为 Boss 类和 Worker 类添加局部成员变量 countDownLatch。
在 Boss 检查之前,调用 countDownLatch.await() 方法来等待员工干完。
在 Worker 干完后,调用 countDownLatch.countDown() 方法来令计数器减一。

工人

  1. package ThreadDemo.CountDownLatchDemo.demo02;
  2. import java.util.concurrent.CountDownLatch;
  3. public class Worker implements Runnable {
  4. gl>private CountDownLatch countDownLatch;
  5. /*
  6. * 员工编号
  7. */
  8. private String workCode;
  9. public Worker(String workCode,CountDownLatch countDownLatch){
  10. this.countDownLatch = countDownLatch;
  11. this.workCode = workCode;
  12. }
  13. @Override
  14. public void run() {
  15. String msg = new StringBuilder()
  16. .append("我是员工")
  17. .append(workCode)
  18. .append(",我正在干活")
  19. .toString();
  20. System.out.println(msg);
  21. gl>this.countDownLatch.countDown();
  22. }
  23. }

老板

  1. package ThreadDemo.CountDownLatchDemo.demo02;
  2. import java.util.concurrent.CountDownLatch;
  3. public class Boss implements Runnable{
  4. gl>private CountDownLatch countDownLatch;
  5. public Boss(CountDownLatch countDownLatch){
  6. this.countDownLatch = countDownLatch;
  7. }
  8. @Override
  9. public void run() {
  10. gl>try {
  11. gl>this.countDownLatch.await();
  12. gl>} catch (InterruptedException e) {
  13. gl>e.printStackTrace();
  14. gl>}
  15. System.out.println("我是老板,我检查了");
  16. }
  17. }

测试

  1. package ThreadDemo.CountDownLatchDemo.demo02;
  2. import java.util.concurrent.CountDownLatch;
  3. import java.util.concurrent.ExecutorService;
  4. import java.util.concurrent.Executors;
  5. public class Program {
  6. public static void main(String[] args) {
  7. CountDownLatch countDownLatch = new CountDownLatch(3);
  8. Worker worker1 =new Worker("worker1",countDownLatch);
  9. Worker worker2 =new Worker("worker2",countDownLatch);
  10. Worker worker3 =new Worker("worker3",countDownLatch);
  11. Boss boss = new Boss(countDownLatch);
  12. ExecutorService executorService = Executors.newCachedThreadPool();
  13. executorService.execute(worker1);
  14. executorService.execute(worker2);
  15. executorService.execute(worker3);
  16. executorService.execute(boss);
  17. executorService.shutdown();
  18. System.out.println("over");
  19. }
  20. }
  21. //输出结果
  22. over
  23. 我是员工worker1,我正在干活
  24. 我是员工worker2,我正在干活
  25. 我是员工worker3,我正在干活
  26. 我是老板,我检查了

输出结果不一定和上面的相同 ,但老板检查肯定是在员工干完活之后。

其他

官方链接 https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html

说明

转载:https://zapldy.iteye.com/blog/746458
略有修改

扫码分享
版权说明
作者:SQBER
文章来源:http://www.sqber.com/articles/CountDownLatch.html
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。