溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java中CountDownLatch進(jìn)行多線程同步詳解及實(shí)例代碼

發(fā)布時(shí)間:2020-08-28 18:19:45 來源:腳本之家 閱讀:125 作者:大愚若智_ 欄目:編程語言

Java中CountDownLatch進(jìn)行多線程同步詳解

CountDownLatch介紹

在前面的Java學(xué)習(xí)筆記中,總結(jié)了Java中進(jìn)行多線程同步的幾個(gè)方法:

1、synchronized關(guān)鍵字進(jìn)行同步。
2、Lock鎖接口及其實(shí)現(xiàn)類ReentrantLock、ReadWriteLock鎖實(shí)現(xiàn)同步。
3、信號(hào)量Semaphore實(shí)現(xiàn)同步。

其中,synchronized關(guān)鍵字和Lock鎖解決的是多個(gè)線程對同一資源的并發(fā)訪問問題。信號(hào)量Semaphore解決的是多副本資源的共享訪問問題。

今天,來學(xué)習(xí)一下Java中的另外一個(gè)多線程同步輔助類:CountDownLatch。官方文檔對CountDownLatch的解釋是:在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個(gè)或多個(gè)線程一直等待。也就是說,CountDownLatch控制某個(gè)或者多個(gè)線程,讓它們等待多個(gè)線程完成某項(xiàng)任務(wù)后,再啟動(dòng)。CountDownLatch主要是用來同步多個(gè)任務(wù)的執(zhí)行,區(qū)別于其他的synchronized關(guān)鍵字,鎖,信號(hào)量是用來同步共享資源的。

CountDownLatch實(shí)現(xiàn)原理簡介:

CountDownLatch內(nèi)部維護(hù)一個(gè)計(jì)數(shù)器,計(jì)數(shù)器的值為待完成的任務(wù)數(shù)N,需要等待這N個(gè)任務(wù)完成的線程調(diào)用

CountDownLatch的await()方法使自己進(jìn)入休眠等待狀態(tài)。

當(dāng)某一個(gè)任務(wù)線程完成某一個(gè)任務(wù)后調(diào)用CountDownLatch的countDown()方法來表示自己的任務(wù)已完成,此時(shí)CountDownLatch的計(jì)數(shù)器值減1,當(dāng)所有的任務(wù)完成式,計(jì)數(shù)器的值為0。當(dāng)計(jì)數(shù)器值為0時(shí),CountDownLatch將喚醒所有因await()方法進(jìn)入休眠的線程。

CountDownLatch的使用:

CountDownLatch的使用主要有3點(diǎn):

1、CountDownLatch的聲明及初始化,在初始化時(shí)需要指定等待完成的任務(wù)數(shù)。

2、某一個(gè)任務(wù)完成時(shí)調(diào)用CountDownLatch的countDown()方法,向CountDownLatch報(bào)告自己的任務(wù)已經(jīng)完成,

3、需要等待任務(wù)完成的線程調(diào)用CountDownLatch的await()方法,調(diào)用后該線程將進(jìn)入休眠,并在所有任務(wù)數(shù)完成后CountDownLatch的計(jì)數(shù)器值為0時(shí),因await()方法進(jìn)行休眠的線程將被喚醒。

在此本人在Java 7并發(fā)編程實(shí)戰(zhàn)手冊該書中的CountDownLatch使用示例的基礎(chǔ)上做了部分改進(jìn),來演示CountDownLatch的使用詳情:

模擬10個(gè)參會(huì)者和一個(gè)主持人參加的一個(gè)會(huì)以,每個(gè)參會(huì)者及主持人需要等待其他的參會(huì)者均到場簽到之后,才能開始會(huì)以并發(fā)言。為此,先創(chuàng)建一個(gè)會(huì)以管理的類VideoConference,其提供一個(gè)arrive()方法供參會(huì)者調(diào)用來進(jìn)行簽到。會(huì)議管理的擁有者是主持人,其等待每個(gè)參會(huì)者的簽到:

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初始化其內(nèi)部的計(jì)數(shù)器,當(dāng)初始化完成后,不能再次初始化 
  } 
  public void arrive(String name){ 
    //每個(gè)需要同步的任務(wù),在任務(wù)完成時(shí),需要調(diào)用該方法 
    countDownLatch.countDown();//countDownLatch內(nèi)部的計(jì)數(shù)器減1 
    System.out.print("arrive:"+name+"\n"); 
    try{ 
      countDownLatch.await();//await方法是線程進(jìn)入休眠,當(dāng)countDownLatch計(jì)數(shù)器為0時(shí),將被喚醒 
      //線程被喚醒,在這里可以執(zhí)行一系列任務(wù) 
      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方法是線程進(jìn)入休眠,當(dāng)countDownLatch計(jì)數(shù)器為0時(shí),將被喚醒 
      //線程被喚醒,在這里可以執(zhí)行一系列任務(wù) 
      System.out.print("all arrived:"+(number-countDownLatch.getCount())+"\n"); 
    }catch (InterruptedException e){ 
      e.printStackTrace(); 
    } 
  } 
} 

創(chuàng)建一個(gè)參會(huì)者類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函數(shù)首先創(chuàng)建了一個(gè)需要10個(gè)參會(huì)者參加的一個(gè)會(huì)議,之后,創(chuàng)建了10個(gè)參會(huì)者并逐個(gè)簽到,在10個(gè)參會(huì)者都簽到之后,每個(gè)參會(huì)者及主持人將被"喚醒"并發(fā)言。

總結(jié):

CountDownLatch類解決的是多線程間的同步等待、任務(wù)協(xié)調(diào)問題,應(yīng)用在如在啟動(dòng)某個(gè)程序的主功能前,需要前置完成配置環(huán)境檢查、網(wǎng)絡(luò)檢查等多個(gè)子任務(wù)等類似的場景。在Java中,除了使用CountDownLatch來實(shí)現(xiàn)多線程間的同步等待以外,還可以使用柵欄技術(shù)CyclicBarrier來實(shí)現(xiàn)多線程間的同步等待、任務(wù)協(xié)調(diào)。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI