亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

首頁 慕課教程 Java并發工具 Java并發工具 同步計數器 CountDownLatch

同步計數器 CountDownLatch

1. 前言

本節帶領大家認識第二個常用的 Java 并發工具類之 CountDownLatch。

本節先介紹 CountDownLatch 工具類表達的概念和最基本用法,接著通過一個生活中的例子為大家解釋 CountDownLatch 工具類的使用場合,然后通過簡單的編碼實現此場景,最后帶領大家熟悉 CountDownLatch 工具類的其他重要方法。

下面我們正式開始介紹吧。

2. 概念解釋

CountDownLatch 工具類從字面理解為 “倒計數鎖”,其內部使用一個計數器進行實現,計數器初始值為線程的數量。當每一個線程完成自己的任務后,計數器的值就會減一。當計數器的值為 0 時,表示所有的線程都已經完成了任務,然后在 CountDownLatch 上等待的線程就可以恢復繼續執行后繼任務。是不是很抽象,其實很簡單,看下面的圖例。
圖片描述
這就是 CountDownLatch 工具類的基本邏輯。概念已經了解了,CountDownLatch 工具類最基本的用法是怎樣的呢?看下面。

3. 基本用法

// 創建一個 CountDownLatch 對象
CountDownLatch countDownLatch = new CountDownLatch(子線程個數);

// 子線程1開始處理邏輯
...
// 子線程執行完所有邏輯進行計數器減1
countDownLatch.countDown();

// 子線程n開始處理邏輯
...
// 子線程執行完所有邏輯進行計數器減1
countDownLatch.countDown();

// 主線程等待所有子線程執行完
countDownLatch.await();
// 主線程繼續執行后繼邏輯
...

是不是很簡單,CountDownLatch 應用在哪些場合比較合適呢?下面我們給出最常用的場景說明。

4. 常用場景

CountDownLatch 經常用于某一線程在開始運行前等待其他關聯線程執行完畢的場合。

比如我們制作一張復雜報表,報表的各部分可以安排對應的一個線程進行計算,只有當所有線程都執行完畢后,再由最終的報表輸出線程進行報表文件生成。

下面我們使用 CountDownLatch 實現這個例子。假設這張報表有 5 個部分,我們總共安排 5 個子線程分別計算,再設置 1 個報表輸出線程用于最終生成報表文件。請看下面代碼。

5. 場景案例

import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class CountDownLatchTest {
    // 創建一個 CountDownLatch 對象,初始化為 5, 代表需要控制同步的子線程個數
    static int threadCount = 5;
    private static CountDownLatch countDownLatch = new CountDownLatch(threadCount);
    // 報表生成主線程
    public static void main(String[] args) throws InterruptedException {
        // 定義報表子線程
        for(int i=1; i<=threadCount; i++) {
            // 開始報表子線程處理
            new Thread(new Runnable() {
                public void run() {
                    // 模擬報表數據計算時間
                    try {
                        Thread.sleep(new Random().nextInt(5000));
                    } catch (Exception e) {}
                    System.out.println( Thread.currentThread().getName() + "已經處理完畢");
                    countDownLatch.countDown();
                }
            }, "報表子線程" + i).start();
        }
        // 主線程等待所有子線程運行完畢后輸出報表文件
        countDownLatch.await();
        System.out.println("報表數據已經全部計算完畢,開始生成報表文件...");
    }
}

運行上面代碼,我們觀察一下運行結果。

報表子線程3已經處理完畢
報表子線程5已經處理完畢
報表子線程1已經處理完畢
報表子線程4已經處理完畢
報表子線程2已經處理完畢
報表數據已經全部計算完畢,開始生成報表文件...

觀察結果,和我們的預期一致。注意體會 CountDownLatch 提供的多線程共同協作的模型。

6. 其他方法介紹

除過上面代碼中使用的最基本的 countDown ()、await () 方法之外,還有兩個方法大家可以了解一下。

  1. await (long, TimeUnit) 方法
    此方法提供了更靈活的等待參數,可以設置等待超時時間。當等待超過了設定的時限,則不再阻塞直接開始后繼處理。

  2. getCount () 方法
    調用此方法,可獲得當前計數器的數值,了解整體處理進度。

7. 小結

本節解釋了 CountDownLatch 的基本邏輯模型,且通過一個簡單的例子,介紹了 CountDownLatch 的使用場景和基本用法。希望大家在學習過程中,多思考勤練習,早日掌握之。