Java中CountDownLatch进行多线程同步详解及实例代码

 更新时间:2017年03月21日 09:49:09   作者:大愚若智_  
这篇文章主要介绍了Java中CountDownLatch进行多线程同步详解及实例代码的相关资料,需要的朋友可以参考下

Java中CountDownLatch进行多线程同步详解

CountDownLatch介绍

在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法:

1、synchronized关键字进行同步。
2、Lock锁接口及其实现类ReentrantLock、ReadWriteLock锁实现同步。
3、信号量Semaphore实现同步。

其中,synchronized关键字和Lock锁解决的是多个线程对同一资源的并发访问问题。信号量Semaphore解决的是多副本资源的共享访问问题。

今天,来学习一下Java中的另外一个多线程同步辅助类:CountDownLatch。官方文档对CountDownLatch的解释是:在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。也就是说,CountDownLatch控制某个或者多个线程,让它们等待多个线程完成某项任务后,再启动。CountDownLatch主要是用来同步多个任务的执行,区别于其他的synchronized关键字,锁,信号量是用来同步共享资源的。

CountDownLatch实现原理简介:

CountDownLatch内部维护一个计数器,计数器的值为待完成的任务数N,需要等待这N个任务完成的线程调用

CountDownLatch的await()方法使自己进入休眠等待状态。

当某一个任务线程完成某一个任务后调用CountDownLatch的countDown()方法来表示自己的任务已完成,此时CountDownLatch的计数器值减1,当所有的任务完成式,计数器的值为0。当计数器值为0时,CountDownLatch将唤醒所有因await()方法进入休眠的线程。

CountDownLatch的使用:

CountDownLatch的使用主要有3点:

1、CountDownLatch的声明及初始化,在初始化时需要指定等待完成的任务数。

2、某一个任务完成时调用CountDownLatch的countDown()方法,向CountDownLatch报告自己的任务已经完成,

3、需要等待任务完成的线程调用CountDownLatch的await()方法,调用后该线程将进入休眠,并在所有任务数完成后CountDownLatch的计数器值为0时,因await()方法进行休眠的线程将被唤醒。

在此本人在Java 7并发编程实战手册该书中的CountDownLatch使用示例的基础上做了部分改进,来演示CountDownLatch的使用详情:

模拟10个参会者和一个主持人参加的一个会以,每个参会者及主持人需要等待其他的参会者均到场签到之后,才能开始会以并发言。为此,先创建一个会以管理的类VideoConference,其提供一个arrive()方法供参会者调用来进行签到。会议管理的拥有者是主持人,其等待每个参会者的签到:

public class VideoConference implements Runnable{ 
  private final CountDownLatch countDownLatch; 
  private int number; 
  public VideoConference(int number) { 
    this.number = number; 
    this.countDownLatch = new CountDownLatch(number);//使用Number初始化其内部的计数器,当初始化完成后,不能再次初始化 
  } 
  public void arrive(String name){ 
    //每个需要同步的任务,在任务完成时,需要调用该方法 
    countDownLatch.countDown();//countDownLatch内部的计数器减1 
    System.out.print("arrive:"+name+"\n"); 
    try{ 
      countDownLatch.await();//await方法是线程进入休眠,当countDownLatch计数器为0时,将被唤醒 
      //线程被唤醒,在这里可以执行一系列任务 
      System.out.print("name:"+name + " say:let's start..." +"\n"); 
    }catch (InterruptedException e){ 
      e.printStackTrace(); 
    } 
  } 
  public void run(){ 
    System.out.print("has arrive:"+(number-countDownLatch.getCount())+"\n"); 
    try{ 
      countDownLatch.await();//await方法是线程进入休眠,当countDownLatch计数器为0时,将被唤醒 
      //线程被唤醒,在这里可以执行一系列任务 
      System.out.print("all arrived:"+(number-countDownLatch.getCount())+"\n"); 
    }catch (InterruptedException e){ 
      e.printStackTrace(); 
    } 
  } 
} 

创建一个参会者类Participant:

public class Participant implements Runnable{ 
  private VideoConference videoConference; 
  private String name; 
 
  public Participant(String name, VideoConference videoConference) { 
    this.name = name; 
    this.videoConference = videoConference; 
  } 
  public void run(){ 
    try { 
      //do something 
      Thread.sleep(50); 
      // 
      videoConference.arrive(name); 
    }catch (InterruptedException e){ 
      e.printStackTrace(); 
    } 
  } 
 
  public static void main(String[] args){ 
    VideoConference videoConference = new VideoConference(10); 
    Thread videoThread = new Thread(videoConference); 
    videoThread.start(); 
    for(int i=0; i<10; i++){ 
      Thread thread = new Thread(new Participant("participant:"+i,videoConference)); 
      thread.start(); 
    } 
  } 
} 

Participant类中的main函数首先创建了一个需要10个参会者参加的一个会议,之后,创建了10个参会者并逐个签到,在10个参会者都签到之后,每个参会者及主持人将被"唤醒"并发言。

总结:

CountDownLatch类解决的是多线程间的同步等待、任务协调问题,应用在如在启动某个程序的主功能前,需要前置完成配置环境检查、网络检查等多个子任务等类似的场景。在Java中,除了使用CountDownLatch来实现多线程间的同步等待以外,还可以使用栅栏技术CyclicBarrier来实现多线程间的同步等待、任务协调。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

相关文章

  • SpringMVC HttpMessageConverter报文信息转换器

    SpringMVC HttpMessageConverter报文信息转换器

    ​​HttpMessageConverter​​​,报文信息转换器,将请求报文转换为Java对象,或将Java对象转换为响应报文。​​​HttpMessageConverter​​​提供了两个注解和两个类型:​​@RequestBody,@ResponseBody​​​,​​RequestEntity,ResponseEntity​​
    2023-01-01
  • 代理模式之Java动态代理实现方法

    代理模式之Java动态代理实现方法

    今天一个偶然的机会我突然想看看JDK的动态代理,因为以前也知道一点,而且只是简单的想测试一下使用,使用很快里就写好了这么几个接口和类,需要的朋友可以参考下
    2012-11-11
  • Quarkus的Spring扩展快速改造Spring项目

    Quarkus的Spring扩展快速改造Spring项目

    这篇文章主要为大家介绍了Quarkus的Spring项目扩展,带大家快速改造Spring项目示例演绎,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-02-02
  • Python文件高级操作函数之文件信息获取与目录操作

    Python文件高级操作函数之文件信息获取与目录操作

    这篇文章主要介绍了Python文件高级操作函数之文件信息获取与目录操作,在Python中,内置了文件(File)对象。在使用文件对象时,首先需要通过内置的open()方法创建一个文件对象,然后通过该对象提供的方法进行一些基本文件操作,需要的朋友可以参考下
    2023-05-05
  • MyBatis Generator介绍及使用方法

    MyBatis Generator介绍及使用方法

    MyBatis Generator 是一款针对 MyBatis 或 iBATIS 设计的代码生成器,由 MyBatis 官方提供,这篇文章主要介绍了MyBatis Generator介绍及使用方法,需要的朋友可以参考下
    2023-06-06
  • Java中join线程操作实例分析

    Java中join线程操作实例分析

    这篇文章主要介绍了Java中join线程操作,结合实例形式分析了java使用join方法操作线程的相关原理与实现技巧,需要的朋友可以参考下
    2019-09-09
  • Java MyBatis框架环境搭建详解

    Java MyBatis框架环境搭建详解

    MyBatis本是apache的一个开源项目iBatis,MyBatis环境的搭建有点麻烦,本章带你了解搭建过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
    2022-08-08
  • fastjson 使用方法详细介绍

    fastjson 使用方法详细介绍

    Fastjson是一个Java语言编写的JSON处理器,由阿里巴巴公司开发。接下来通过本文给大家分享fastjson 使用方法详细介绍,感兴趣的朋友一起看看吧
    2017-11-11
  • JAVA字符串拼接常见方法汇总

    JAVA字符串拼接常见方法汇总

    这篇文章主要介绍了JAVA字符串拼接常见方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 如何使用Java操作Zookeeper

    如何使用Java操作Zookeeper

    这篇文章主要介绍了如何使用Java操作Zookeeper,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-04-04

最新评论