最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java并發(fā)利器CountDownLatch深度解析與實(shí)戰(zhàn)應(yīng)用小結(jié)

 更新時(shí)間:2025年06月18日 08:49:12   作者:一只劃水的程序猿  
CountDownLatch就像一個(gè)倒計(jì)時(shí)器,當(dāng)所有任務(wù)完成后,主線程才繼續(xù)執(zhí)行,本文將通過簡單易懂的方式,帶你掌握這個(gè)強(qiáng)大的并發(fā)工具,需要的朋友可以參考下

Java并發(fā)利器:CountDownLatch深度解析與實(shí)戰(zhàn)應(yīng)用

多線程編程中,讓主線程等待所有子任務(wù)完成是個(gè)常見需求。CountDownLatch就像一個(gè)倒計(jì)時(shí)器,當(dāng)所有任務(wù)完成后,主線程才繼續(xù)執(zhí)行。本文將通過簡單易懂的方式,帶你掌握這個(gè)強(qiáng)大的并發(fā)工具。

一、CountDownLatch是什么?

1. 基本概念

CountDownLatch就是一個(gè)"倒計(jì)數(shù)門閂":

  • 倒計(jì)數(shù):從指定數(shù)字開始遞減到0
  • 門閂:當(dāng)計(jì)數(shù)為0時(shí),門閂打開,等待的線程繼續(xù)執(zhí)行
  • 一次性:用完即棄,不能重置

2. 基本用法

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        // 創(chuàng)建計(jì)數(shù)器,初始值為3
        CountDownLatch latch = new CountDownLatch(3);
        // 啟動(dòng)3個(gè)任務(wù)
        for (int i = 0; i < 3; i++) {
            final int taskId = i;
            new Thread(() -> {
                System.out.println("任務(wù)" + taskId + "開始執(zhí)行");
                try {
                    Thread.sleep(2000); // 模擬任務(wù)執(zhí)行
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任務(wù)" + taskId + "執(zhí)行完成");
                latch.countDown(); // 計(jì)數(shù)器減1
            }).start();
        }
        System.out.println("主線程等待所有任務(wù)完成...");
        latch.await(); // 等待計(jì)數(shù)器變?yōu)?
        System.out.println("所有任務(wù)完成,主線程繼續(xù)執(zhí)行");
    }
}

運(yùn)行結(jié)果:

主線程等待所有任務(wù)完成...
任務(wù)0開始執(zhí)行
任務(wù)1開始執(zhí)行
任務(wù)2開始執(zhí)行
任務(wù)0執(zhí)行完成
任務(wù)1執(zhí)行完成
任務(wù)2執(zhí)行完成
所有任務(wù)完成,主線程繼續(xù)執(zhí)行

二、核心API介紹

CountDownLatch只有4個(gè)關(guān)鍵方法:

public class CountDownLatchAPI {
    public void demonstrateAPI() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        // 1. countDown() - 計(jì)數(shù)器減1
        latch.countDown();
        // 2. await() - 等待計(jì)數(shù)器變?yōu)?
        latch.await();
        // 3. await(時(shí)間, 單位) - 超時(shí)等待
        boolean finished = latch.await(5, TimeUnit.SECONDS);
        // 4. getCount() - 獲取當(dāng)前計(jì)數(shù)值
        long count = latch.getCount();
        System.out.println("剩余計(jì)數(shù): " + count);
    }
}

三、經(jīng)典應(yīng)用場景

場景1:等待多個(gè)任務(wù)完成

最常用的場景,主線程等待所有子任務(wù)完成:

public class WaitMultipleTasksDemo {
    // 模擬訂單處理:需要等待庫存檢查、用戶驗(yàn)證、支付驗(yàn)證都完成
    public void processOrder(String orderId) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        // 庫存檢查
        new Thread(() -> {
            try {
                System.out.println("開始庫存檢查...");
                Thread.sleep(1000);
                System.out.println("庫存檢查完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        }).start();
        // 用戶驗(yàn)證
        new Thread(() -> {
            try {
                System.out.println("開始用戶驗(yàn)證...");
                Thread.sleep(1500);
                System.out.println("用戶驗(yàn)證完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        }).start();
        // 支付驗(yàn)證
        new Thread(() -> {
            try {
                System.out.println("開始支付驗(yàn)證...");
                Thread.sleep(800);
                System.out.println("支付驗(yàn)證完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        }).start();
        System.out.println("等待所有驗(yàn)證完成...");
        latch.await();
        System.out.println("訂單處理完成: " + orderId);
    }
}

場景2:控制并發(fā)啟動(dòng)

讓多個(gè)線程同時(shí)開始執(zhí)行:

public class ConcurrentStartDemo {
    // 模擬賽跑:所有選手同時(shí)起跑
    public void startRace() throws InterruptedException {
        int runnerCount = 5;
        CountDownLatch startGun = new CountDownLatch(1); // 發(fā)令槍
        CountDownLatch finish = new CountDownLatch(runnerCount); // 終點(diǎn)線
        // 創(chuàng)建選手
        for (int i = 0; i < runnerCount; i++) {
            final int runnerId = i;
            new Thread(() -> {
                try {
                    System.out.println("選手" + runnerId + "準(zhǔn)備就緒");
                    startGun.await(); // 等待發(fā)令槍
                    // 開始跑步
                    System.out.println("選手" + runnerId + "開始跑步");
                    Thread.sleep(new Random().nextInt(3000)); // 模擬跑步時(shí)間
                    System.out.println("選手" + runnerId + "到達(dá)終點(diǎn)");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    finish.countDown();
                }
            }).start();
        }
        Thread.sleep(2000); // 等待選手準(zhǔn)備
        System.out.println("預(yù)備...開始!");
        startGun.countDown(); // 發(fā)令
        finish.await(); // 等待所有選手完成
        System.out.println("比賽結(jié)束!");
    }
}

場景3:分段計(jì)算

將大任務(wù)拆分成小任務(wù)并行計(jì)算:

public class ParallelCalculationDemo {
    // 并行計(jì)算數(shù)組的和
    public long calculateSum(int[] array) throws InterruptedException {
        int threadCount = 4;
        CountDownLatch latch = new CountDownLatch(threadCount);
        AtomicLong totalSum = new AtomicLong(0);
        int chunkSize = array.length / threadCount;
        for (int i = 0; i < threadCount; i++) {
            final int start = i * chunkSize;
            final int end = (i == threadCount - 1) ? array.length : (i + 1) * chunkSize;
            new Thread(() -> {
                long partialSum = 0;
                for (int j = start; j < end; j++) {
                    partialSum += array[j];
                }
                totalSum.addAndGet(partialSum);
                System.out.println("線程計(jì)算范圍[" + start + "," + end + "),結(jié)果:" + partialSum);
                latch.countDown();
            }).start();
        }
        latch.await();
        return totalSum.get();
    }
    public static void main(String[] args) throws InterruptedException {
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        ParallelCalculationDemo demo = new ParallelCalculationDemo();
        long result = demo.calculateSum(array);
        System.out.println("總和:" + result);
    }
}

四、使用注意事項(xiàng)

1. 異常處理要點(diǎn)

核心原則:無論是否異常,都要調(diào)用countDown()

// ? 正確寫法
new Thread(() -> {
    try {
        // 業(yè)務(wù)邏輯
        doSomething();
    } catch (Exception e) {
        System.err.println("任務(wù)異常:" + e.getMessage());
    } finally {
        latch.countDown(); // 確保在finally中調(diào)用
    }
}).start();
// ? 錯(cuò)誤寫法
new Thread(() -> {
    try {
        doSomething();
        latch.countDown(); // 異常時(shí)不會(huì)執(zhí)行,導(dǎo)致死鎖
    } catch (Exception e) {
        System.err.println("任務(wù)異常:" + e.getMessage());
        // 忘記調(diào)用countDown()
    }
}).start();

2. 避免無限等待

// 設(shè)置超時(shí)時(shí)間,避免無限等待
boolean finished = latch.await(10, TimeUnit.SECONDS);
if (finished) {
    System.out.println("所有任務(wù)完成");
} else {
    System.out.println("等待超時(shí),可能有任務(wù)失敗");
}

3. 合理使用線程池

public void useWithThreadPool() throws InterruptedException {
    CountDownLatch latch = new CountDownLatch(5);
    ExecutorService executor = Executors.newFixedThreadPool(3);
    for (int i = 0; i < 5; i++) {
        final int taskId = i;
        executor.submit(() -> {
            try {
                System.out.println("執(zhí)行任務(wù)" + taskId);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                latch.countDown();
            }
        });
    }
    latch.await();
    executor.shutdown(); // 關(guān)閉線程池
    System.out.println("所有任務(wù)完成");
}

五、實(shí)際項(xiàng)目案例

案例:系統(tǒng)啟動(dòng)初始化

public class SystemInitializer {
    public boolean initializeSystem() {
        System.out.println("開始系統(tǒng)初始化...");
        CountDownLatch latch = new CountDownLatch(4);
        AtomicBoolean success = new AtomicBoolean(true);
        // 數(shù)據(jù)庫初始化
        new Thread(() -> {
            try {
                System.out.println("初始化數(shù)據(jù)庫連接...");
                Thread.sleep(2000);
                System.out.println("數(shù)據(jù)庫初始化完成");
            } catch (InterruptedException e) {
                success.set(false);
            } finally {
                latch.countDown();
            }
        }).start();
        // Redis初始化
        new Thread(() -> {
            try {
                System.out.println("初始化Redis連接...");
                Thread.sleep(1000);
                System.out.println("Redis初始化完成");
            } catch (InterruptedException e) {
                success.set(false);
            } finally {
                latch.countDown();
            }
        }).start();
        // 配置加載
        new Thread(() -> {
            try {
                System.out.println("加載系統(tǒng)配置...");
                Thread.sleep(800);
                System.out.println("配置加載完成");
            } catch (InterruptedException e) {
                success.set(false);
            } finally {
                latch.countDown();
            }
        }).start();
        // 服務(wù)注冊(cè)
        new Thread(() -> {
            try {
                System.out.println("注冊(cè)服務(wù)...");
                Thread.sleep(1500);
                System.out.println("服務(wù)注冊(cè)完成");
            } catch (InterruptedException e) {
                success.set(false);
            } finally {
                latch.countDown();
            }
        }).start();
        try {
            boolean finished = latch.await(10, TimeUnit.SECONDS);
            if (finished && success.get()) {
                System.out.println("系統(tǒng)初始化成功!");
                return true;
            } else {
                System.out.println("系統(tǒng)初始化失敗!");
                return false;
            }
        } catch (InterruptedException e) {
            System.out.println("初始化被中斷");
            return false;
        }
    }
    public static void main(String[] args) {
        SystemInitializer initializer = new SystemInitializer();
        initializer.initializeSystem();
    }
}

六、總結(jié)

CountDownLatch是Java并發(fā)編程中的實(shí)用工具,它的核心價(jià)值在于:

?? 核心特點(diǎn)

  • 簡單易用:API簡潔,概念清晰
  • 線程安全:內(nèi)部實(shí)現(xiàn)保證多線程安全
  • 靈活應(yīng)用:適合多種并發(fā)協(xié)作場景

?? 使用要點(diǎn)

  • 異常安全:在finally中調(diào)用countDown()
  • 超時(shí)控制:使用帶超時(shí)的await()方法
  • 一次性使用:CountDownLatch不能重置
  • 合理設(shè)計(jì):根據(jù)實(shí)際任務(wù)數(shù)量設(shè)置計(jì)數(shù)器

?? 適用場景

  • 主線程等待多個(gè)子任務(wù)完成
  • 控制多個(gè)線程同時(shí)開始執(zhí)行
  • 分段并行計(jì)算后匯總結(jié)果
  • 系統(tǒng)啟動(dòng)時(shí)的組件初始化

掌握CountDownLatch,讓你的多線程程序更加優(yōu)雅和高效!

到此這篇關(guān)于Java并發(fā)利器:CountDownLatch深度解析與實(shí)戰(zhàn)應(yīng)用的文章就介紹到這了,更多相關(guān)Java并發(fā)利器:CountDownLatch深度解析與實(shí)戰(zhàn)應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

蓬溪县| 南平市| 东至县| 都昌县| 龙山县| 东至县| 剑阁县| 博乐市| 辽源市| 临朐县| 余庆县| 紫云| 乡宁县| 齐河县| 兴宁市| 高碑店市| 周至县| 高要市| 尤溪县| 台前县| 垦利县| 栖霞市| 临汾市| 哈巴河县| 翼城县| 游戏| 北票市| 丰县| 古浪县| 宝山区| 榆树市| 马龙县| 安塞县| 西畴县| 巴东县| 化州市| 洛南县| 玛沁县| 正蓝旗| 济南市| 武安市|