java并发编程JUC第九篇:CountDownLatch线程同步

逻辑追月客
• 阅读 1545

java并发编程JUC第九篇:CountDownLatch线程同步

在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口、ConcurrentHashMap,本文为系列文章第九篇。

CountDownLatch是一种线程同步辅助工具,它允许一个或多个线程等待其他线程正在执行的一组操作完成。CountDownLatch的概念在java并发编程中非常常见,面试也会经常被问到,所以一定要好好理解掌握。在这篇文章中,我将介绍以下几点

  • CountDownLatch是什么?
  • CountDownLatch 如何工作
  • CountDownLatch 代码例子

CountDownLatch是什么?

CountDownLatch与其他并发编程工具类,如CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue等在java.util.concurrent包中与JDK 1.5一起被引入。CountDownLatch能让一个java线程等待其他线程完成任务,比如Application的主线程等待,直到其他负责启动框架服务的服务线程完成所有服务的启动。

CountDownLatch用线程数来初始化一个计数器,每当一个线程完成执行时,这个计数器就会递减。当计数为零时,表示所有线程都已完成执行,处于等待状态的主线程可以继续执行。

java并发编程JUC第九篇:CountDownLatch线程同步

下面我们使用伪代码的方式描述CountDownLatch 的作用

  • 主线程启动,并为N个线程(假设n=3)初始化CountDownLatch(n)
  • 启动n个线程
  • 主线程阻塞等待
  • 线程1执行完成,CountDownLatch -1 = 2,主线程继续阻塞
  • 线程3执行完成,CountDownLatch -1 = 1,主线程继续阻塞
  • 线程4执行完成,CountDownLatch -1 = 0,主线程恢复执行

CountDownLatch 如何工作

CountDownLatch.java类里面定义了一个构造函数。count实质上是线程数,这个值只能设置一次,CountDownLatch没有提供方法来重置这个数

CountDownLatch.public CountDownLatch(int count) {...}

使用CountDownLatch的主线程要去等待其他线程执行完成,所以这个主线程必须在启动其他线程后立即调用 CountDownLatch.await() 方法,该方法阻塞主线程处于等待状态,直到其他线程执行完毕,才会停止阻塞。

其他N个线程必须有CountDownLatch对象的引用,因为它们需要通知CountDownLatch对象它们已经完成任务。这个通知是由方法CountDownLatch.countDown()来完成的,每调用一次该方法,就会将构造函数中设置的初始计数count减少1,所以当所有N个线程都调用了这个方法后count计数达到0,主线程就可以不受await()方法阻塞恢复执行了。

所以CountDownLatch特别适合于那些需要等待N个线程完成后再开始执行的场景。例如一个应用程序的启动类,在处理用户请求之前,要确保所有N个外部系统都是处于运行状态的。

CountDownLatch 代码例子

假设我们的应用程序主线程启动之前,要检查另外4个程序是否准备就绪,只有其他的4个程序准备就绪,我们的主程序才能继续执行。就可以使用下面的代码来操作:

import java.util.concurrent.CountDownLatch;

public class Tester {
   public static void main(String args[]) {
      //设置计数器 counter = 4 ,等于线程数
      CountDownLatch countDownLatch = new CountDownLatch(4);

      Thread app1 = new Thread(new Application("App1",  countDownLatch));
      Thread app2 = new Thread(new Application("App2",  countDownLatch));          
      Thread app3 = new Thread(new Application("App3",  countDownLatch));
      Thread app4 = new Thread(new Application("App4",  countDownLatch));  
 
      // 启动多线程去检查其他四个程序的可用状态
      app1.start();
      app2.start();
      app3.start();
      app4.start();

      try {
         //主线程调用await进行等待,等待上述四个线程正常完成
         countDownLatch.await();            
         //上述四个线程检查的应用程序启动正常之后, 打印如下信息
         System.out.println("All applications are up and running.");
      } catch(InterruptedException e) {
         System.out.println(e.getMessage());
      }        
   }
}

子线程程序,每一个线程都持有countDownLatch对象,线程正常执行完成之时,使用countDownLatch.countDown()方法将countDownLatch对象的计数器减1。

class Application implements Runnable {
   private String name; //应用程序名称
   private CountDownLatch countDownLatch; 

   public Application(String name, CountDownLatch countDownLatch) {
      this.name = name;
      this.countDownLatch = countDownLatch;
   }

   public void run() {
      try {
         System.out.println(name + " started. ");
         Thread.sleep(1000);
      } catch (InterruptedException e) {
         System.out.println(e.getMessage());
      }
      System.out.println( name + " is Up and running.");
      //将countDownLatch计数器的值减1
      countDownLatch.countDown();    
   }
}

上述程序的打印输出结果是,可以结合输出结果去理解上文中讲述的CountDownLatch 工作原理:

App2 started.  
App3 started.  
App1 started.  
App4 started.  
App1 is Up and running.
App3 is Up and running.
App4 is Up and running.
App2 is Up and running.
All applications are up and running.

欢迎关注我的博客,里面有很多精品合集

本文转载注明出处(必须带连接,不能只转文字):字母哥博客 - zimug.com

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java并发编程,volatile内存实现和原理
前面的博文说了java的内存模型(https://my.oschina.net/90888/blog/1627359),介绍了java内存模型(https://my.oschina.net/90888/blog/1627359)的基础,此篇文章来说一下volatile关键字,这个在并发编程中,占有举足轻重地位的关键字。在java5.0之前它
Wesley13 Wesley13
3年前
java并发中CountDownLatch的使用
java并发中CountDownLatch的使用在java并发中,控制共享变量的访问非常重要,有时候我们也想控制并发线程的执行顺序,比如:等待所有线程都执行完毕之后再执行另外的线程,或者等所有线程都准备好了才开始所有线程的执行等。这个时候我们就可以使用到CountDownLatch。简单点讲,CountDownLatch存有一个放在QueuedS
【开发宝典】Java并发系列教程(四)
本文将给大家分享Java并发编程相关的知识点,具体将对Java常见的并发编程方式和手段进行总结,以便可以从使用角度更好地感知Java并发编程带来的效果。
Wesley13 Wesley13
3年前
JUC并发编程之:简单概述(一)
JUC并发编程之:简单概述(一)内容概述:·进程和线程、并发和并行、同步和异步概念·如何查看和关闭进程·Java线程常用的类和方法一、概念:一、进程与线程1·进程·程序由指令和数据组成,但这些指令要运行,数据要读写,就
Wesley13 Wesley13
3年前
JUC
Java5.0在java.util.concurrent包中提供了多种并发容器类来改进同步容器的性能。CountDownLatch一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一
Stella981 Stella981
3年前
CountDownLatch
CountDownLatch\TOC\一.介绍CountDownLatch是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,它们都存在于java.util.concurrent包下。Co
Wesley13 Wesley13
3年前
Java并发编程指南
  多线程是实现并发机制的一种有效手段。在Java中实现多线程有两种手段,一种是继承Thread类,另一种就是实现Runnable/Callable接口。  java.util.concurrent包是专为Java并发编程而设计的包。类图如下:!(https://oscimg.oschina.net/oscnet/29ddbb
可莉 可莉
3年前
2021 程序员修炼内功必备:阿里新产 Java 并发编程原理笔记(全彩版)限时开源!
写在前面:近年来在大厂的面试中,高并发不但占比较多,而且已经不局限于并发工具的使用,更多的会深入到底的层实现原理,这样能考察候程序员的内功,看其是否能知其所以然。关于市面上关于Java并发编程的资料感觉有些知识点不是很清晰,于是展开了对Java并发编程原理的讨论。在这收集整理了这些Java并发编程原理整理成书籍,分享给大家。目录
Stella981 Stella981
3年前
2021 程序员修炼内功必备:阿里新产 Java 并发编程原理笔记(全彩版)限时开源!
写在前面:近年来在大厂的面试中,高并发不但占比较多,而且已经不局限于并发工具的使用,更多的会深入到底的层实现原理,这样能考察候程序员的内功,看其是否能知其所以然。关于市面上关于Java并发编程的资料感觉有些知识点不是很清晰,于是展开了对Java并发编程原理的讨论。在这收集整理了这些Java并发编程原理整理成书籍,分享给大家。目录