欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-03-04 20:27:12
java中countdownlatch进行多线程同步详解 countdownlatch介绍 在前面的java学习笔记中,总结了java中进行多线程同步的几个方法:...

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来实现多线程间的同步等待、任务协调。

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