java并发编程JUC CountDownLatch线程同步

 更新时间:2021年09月02日 17:02:20   作者:字母哥博客  
这篇文章主要介绍CountDownLatch是什么、CountDownLatch 如何工作、CountDownLatch 的代码例子来展开对java并发编程JUC CountDownLatch线程同步,需要的朋友可以参考下面文章内容

java并发编程JUC CountDownLatch线程同步

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

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

1、CountDownLatch是什么?

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

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

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

2、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个外部系统都是处于运行状态的。

3、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.

到此这篇关于java并发编程JUC CountDownLatch线程同步的文章就介绍到这了,更多相关java JUC CountDownLatch线程同步内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 轻松理解Java面试和开发中的IoC(控制反转)

    轻松理解Java面试和开发中的IoC(控制反转)

    在Java开发中,IoC意 味着将你设计好的类交给系统去控制,而不是在你的类内部控制。这称为控制反转。下文给大家介绍Java面试和开发中的IoC(控制反转)知识,需要的朋友参考下吧
    2017-07-07
  • 使用ServletInputStream在拦截器或过滤器中应用后重写

    使用ServletInputStream在拦截器或过滤器中应用后重写

    这篇文章主要介绍了使用ServletInputStream在拦截器或过滤器中应用后重写,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Springboot 通过FastJson实现bean对象和Json字符串互转问题

    Springboot 通过FastJson实现bean对象和Json字符串互转问题

    这篇文章主要介绍了Springboot 通过FastJson实现bean对象和Json字符串互转,本文尝试验证两种场景给大家详细介绍,对Springboot FastJson实现bean和Json互转问题,感兴趣的朋友一起看看吧
    2022-08-08
  • 使用Idea连接MySQL的详细步骤总结

    使用Idea连接MySQL的详细步骤总结

    今天给大家带来的是关于IDEA连接数据库的问题,文章围绕着使用Idea连接MySQL的详细步骤展开,文中有非常详细的介绍及图文示例,需要的朋友可以参考下
    2021-06-06
  • MyBatis实现动态SQL的实现方法

    MyBatis实现动态SQL的实现方法

    这篇文章主要介绍了MyBatis实现动态SQL的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • 自定义注解实现Spring容器注入Bean方式(类似于mybatis的@MapperScans)

    自定义注解实现Spring容器注入Bean方式(类似于mybatis的@MapperScans)

    本文介绍了如何通过自定义注解@MyService和@MyServiceScans在SpringBoot项目中自动将指定包下的类注入Spring容器,详细解释了创建自定义注解、定义包扫描器ClassPathBeanDefinitionScanner的作用与实现
    2024-09-09
  • 关于mybatis3中几个@Provider的使用方式

    关于mybatis3中几个@Provider的使用方式

    这篇文章主要介绍了关于mybatis3中几个@Provider的使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • Spring Kafka中如何通过参数配置解决超时问题详解

    Spring Kafka中如何通过参数配置解决超时问题详解

    这篇文章主要给大家介绍了关于Spring Kafka中如何通过参数配置解决超时问题的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-01-01
  • Java 中的变量类型

    Java 中的变量类型

    这篇文章主要介绍了Java 中的变量类型,一般包括局部变量、成员变量、类变量,下面文章对这三种内容的变量做了一个详细介绍,需要的朋友可以参考一下
    2021-11-11
  • 使用@PathVariable注解如何实现动态传值

    使用@PathVariable注解如何实现动态传值

    这篇文章主要介绍了使用@PathVariable注解如何实现动态传值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10

最新评论