中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

Java中CountDownLatch的原理是什么

發布時間:2021-05-11 15:29:30 來源:億速云 閱讀:192 作者:Leah 欄目:編程語言

本篇文章為大家展示了Java中CountDownLatch的原理是什么,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

Java的特點有哪些

Java的特點有哪些 1.Java語言作為靜態面向對象編程語言的代表,實現了面向對象理論,允許程序員以優雅的思維方式進行復雜的編程。 2.Java具有簡單性、面向對象、分布式、安全性、平臺獨立與可移植性、動態性等特點。 3.使用Java可以編寫桌面應用程序、Web應用程序、分布式系統和嵌入式系統應用程序等。

一、CountDownLatch

【1】CountDownLatch是什么?

CountDownLatch,英文翻譯為倒計時鎖存器,是一個同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或

多個線程一直等待。

閉鎖可以延遲線程的進度直到其到達終止狀態,閉鎖可以用來確保某些活動直到其他活動都完成才繼續執行:

  • 確保某個計算在其需要的所有資源都被初始化之后才繼續執行;

  • 確保某個服務在其依賴的所有其他服務都已經啟動之后才啟動;

  • 等待直到某個操作所有參與者都準備就緒再繼續執行;

CountDownLatch有一個正數計數器,countDown()方法對計數器做減操作,await()方法等待計數器達到0。所有await的線程都會阻塞直到計數器為0或者等待線程中斷或者超時。

閉鎖(倒計時鎖)主要用來保證完成某個任務的先決條件滿足。是一個同步工具類,用來協調多個線程之間的同步。這個工具通常用來控制線程等待,它可以讓某一個線程等待直到倒計時結束,再開始執行。

【2】CountDownLatch的兩種典型用法

①某一線程在開始運行前等待n個線程執行完畢。

將 CountDownLatch 的計數器初始化為n :new CountDownLatch(n),每當一個任務線程執行完畢,就將計數器減1 countdownlatch.countDown(),當計數器的值變為0時,在CountDownLatch上 await() 的線程就會被喚醒。一個典型應用場景就是啟動一個服務時,主線程需要等待多個組件加載完畢,之后再繼續執行。

②實現多個線程開始執行任務的最大并行性。

注意是并行性,不是并發,強調的是多個線程在某一時刻同時開始執行。類似于賽跑,將多個線程放到起點,等待發令槍響,然后同時開跑。做法是初始化一個共享的 CountDownLatch 對象,將其計數器初始化為 1 :new CountDownLatch(1),多個線程在開始執行任務前首先 coundownlatch.await(),當主線程調用 countDown() 時,計數器變為0,多個線程同時被喚醒。

如下例所示,在多線程運行的情況下,計算多線程耗費的時間:

public class TestCountDownLatch {
  //CountDownLatch 為唯一的、共享的資源
  static CountDownLatch countDownLatch = new CountDownLatch(5);

  static class LatchDemo extends Thread{
    @Override
    public void run() {
      int sum = 0;
      for (int i = 0; i < 1000000; i++) {
        sum++;
      }
      System.out.println(getName()+"計算結果:"+sum);
      countDownLatch.countDown();
    }
  }
  public static void main(String[] args) throws InterruptedException {

    long begin = System.currentTimeMillis();
    System.out.println("開始了-----"+begin);
    for (int i = 0; i < 5; i++) {
      new LatchDemo().start();
    }
    countDownLatch.await();

    long end = System.currentTimeMillis();
    System.out.println("結束了-----"+end);
    System.out.println("總共用時:"+(end-begin));
  }
}

/**
開始了-----1571144894551
Thread-3計算結果:1000000
Thread-0計算結果:1000000
Thread-1計算結果:1000000
Thread-2計算結果:1000000
Thread-4計算結果:1000000
結束了-----1571144894559
總共用時:8
*/

二、CyclicBarrier

【1】CyclicBarrier是什么?
CyclicBarrier即柵欄類,與CountDownLatch類似。它能阻塞一組線程直到某個事件的發生。柵欄與閉鎖的關鍵區別在于,所有的線程必須同時到達柵欄位置,才能繼續執行。

CyclicBarrier可以使一定數量的線程反復地在柵欄位置處匯集。當線程到達柵欄位置時將調用await方法,這個方法將阻塞直到所有線程都到達柵欄位置。如果所有線程都到達柵欄位置,那么柵欄將打開,此時所有的線程都將被釋放,而柵欄將被重置以便下次使用。

【2】CyclicBarrier構造方法

public CyclicBarrier(int parties) {
  this(parties, null);
}

public CyclicBarrier(int parties, Runnable barrierAction) {
  if (parties <= 0) throw new IllegalArgumentException();
  this.parties = parties;
  this.count = parties;
  this.barrierCommand = barrierAction;
}

CyclicBarrier默認的構造方法是CyclicBarrier(int parties),其參數表示屏障攔截的線程數量,每個線程使用await()方法告訴CyclicBarrier我已經到達了屏障,然后當前線程被阻塞。

CyclicBarrier的另一個構造函數CyclicBarrier(int parties, Runnable barrierAction),用于線程到達屏障時,優先執行barrierAction,方便處理更復雜的業務場景。

【3】CyclicBarrier應用示例

public class CyclicBarrierTest {
  // 自定義工作線程
  private static class Worker extends Thread {
    private CyclicBarrier cyclicBarrier;
    
    public Worker(CyclicBarrier cyclicBarrier) {
      this.cyclicBarrier = cyclicBarrier;
    }
    
    @Override
    public void run() {
      super.run();
      
      try {
        System.out.println(Thread.currentThread().getName() + "開始等待其他線程");
        cyclicBarrier.await();
        System.out.println(Thread.currentThread().getName() + "開始執行");
        // 工作線程開始處理,這里用Thread.sleep()來模擬業務處理
        Thread.sleep(1000);
        System.out.println(Thread.currentThread().getName() + "執行完畢");
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
 
  public static void main(String[] args) {
    int threadCount = 3;
    CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
    
    for (int i = 0; i < threadCount; i++) {
      System.out.println("創建工作線程" + i);
      Worker worker = new Worker(cyclicBarrier);
      worker.start();
    }
  }
}
/**
創建工作線程0
創建工作線程1
Thread-0開始等待其他線程
創建工作線程2
Thread-1開始等待其他線程
Thread-2開始等待其他線程
Thread-2開始執行
Thread-0開始執行
Thread-1開始執行
Thread-1執行完畢
Thread-0執行完畢
Thread-2執行完畢
*/

在上述代碼中,我們自定義的工作線程必須要等所有參與線程開始之后才可以執行,我們可以使用CyclicBarrier類來幫助我們完成。從程序的執行結果中也可以看出,所有的工作線程都運行await()方法之后都到達了柵欄位置,然后,3個工作線程才開始執行業務處理。

【4】CyclicBarrier和CountDownLatch的區別

  • CountDownLatch的計數器只能使用一次,而CyclicBarrier的計數器可以使用reset()方法重置,可以使用多次,所以CyclicBarrier能夠處理更為復雜的場景;

  • CyclicBarrier還提供了一些其他有用的方法,比如getNumberWaiting()方法可以獲得CyclicBarrier阻塞的線程數量,isBroken()方法用來了解阻塞的線程是否被中斷;

  • CountDownLatch允許一個或多個線程等待一組事件的產生,而CyclicBarrier用于等待其他線程運行到柵欄位置。

三、Semaphore

【1】Semaphore是什么?
信號量(Semaphore),又被稱為信號燈,在多線程環境下用于協調各個線程, 以保證它們能夠正確、合理的使用公共資源。信號量維護了一個許可集,我們在初始化Semaphore時需要為這個許可集傳入一個數量值,該數量值代表同一時間能訪問共享資源的線程數量。

【2】Semaphore基本用法

線程可以通過acquire()方法獲取到一個許可,然后對共享資源進行操作,注意如果許可集已分配完了,那么線程將進入等待狀態,直到其他線程釋放許可才有機會再獲取許可,線程釋放一個許可通過release()方法完成,"許可"將被歸還給Semaphore。

【3】Semaphore實現互斥鎖

public class TestSemaphore {
  //初始化為1,互斥信號量
  private final static Semaphore mutex = new Semaphore(1);

  static class thread extends Thread{
    @Override
    public void run() {
      try {
        mutex.acquire();
        System.out.println(getName()+"開始工作");
      } catch (InterruptedException e) {
        e.printStackTrace();
      }finally {
        //使用完成釋放鎖
        mutex.release();
        System.out.println("鎖釋放!!!");
      }
    }
  }
  public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
      new Thread(new thread(),String.valueOf(i)).start();
    }
  }
}

創建一個數量為1的互斥信號量Semaphore,然后并發執行10個線程,在線程中利用Semaphore控制線程的并發執行,因為信號量數值只有1,因此每次只能一條線程執行,其他線程進入等待狀態。

四、Callable、Future和FutureTask

Java中CountDownLatch的原理是什么

Future接口,一般都是取回Callable執行的狀態用的。其中的主要方法:

  • cancel,取消Callable的執行,當Callable還沒有完成時

  • get,獲得Callable的返回值

  • isCanceled,判斷是否取消了

  • isDone,判斷是否完成

上述內容就是Java中CountDownLatch的原理是什么,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

包头市| 永安市| 金溪县| 岗巴县| 成安县| 汉沽区| 宜城市| 双城市| 中江县| 怀来县| 垫江县| 富川| 诸城市| 寻乌县| 噶尔县| 台北市| 嘉兴市| 高要市| 西充县| 若羌县| 和平区| 堆龙德庆县| 贵德县| 武威市| 安龙县| 双峰县| 阳山县| 宁化县| 涿鹿县| 什邡市| 东阳市| 康保县| 璧山县| 桦南县| 乌恰县| 宿松县| 洛南县| 上高县| 剑阁县| 卓资县| 宁化县|