Java CountDownLatch 深度解析:原理、应用与实践指南

在这里插入图片描述

一、CountDownLatch 核心概念解析

1.1 什么是 CountDownLatch?

CountDownLatch 是 Java 并发包(java.util.concurrent)中的一个同步辅助类,它允许一个或多个线程等待其他线程完成操作后再继续执行。可以将其理解为一个倒计时门闩,当计数器减到零时,等待的线程才会被释放。

import java.util.concurrent.CountDownLatch;

/**
 * CountDownLatch 基本结构示例
 * 
 * 核心特性:
 * 1. 一次性使用:计数器归零后无法重置
 * 2. 不可逆性:计数器只能递减,不能递增
 * 3. 线程安全:内部使用AQS实现,保证线程安全
 * 4. 等待机制:支持多个线程同时等待
 */
public class CountDownLatchStructure {
    
    // CountDownLatch 的内部状态
    class LatchState {
        private int count;  // 计数器
        
        public LatchState(int count) {
            if (count < 0) {
                throw new IllegalArgumentException("count < 0");
            }
            this.count = count;
        }
        
        public void countDown() {
            synchronized (this) {
                if (count > 0) {
                    count--;
                }
            }
        }
        
        public boolean await() throws InterruptedException {
            synchronized (this) {
                while (count > 0) {
                    this.wait();  // 等待计数器归零
                }
                return true;
            }
        }
    }
    
    public static void main(String[] args) {
        // 创建 CountDownLatch,初始化计数器为3
        CountDownLatch latch = new CountDownLatch(3);
        
        System.out.println("CountDownLatch 创建完成,初始计数器 = " + 3);
        System.out.println("等待线程将阻塞,直到计数器归零");
    }
}

1.2 CountDownLatch 与相关工具对比

特性CountDownLatchCyclicBarrierSemaphorePhaser
核心功能等待其他线程完成线程互相等待控制并发数更灵活的同步
重用性一次性可重用可重用可重用
计数器方向递减递增增减复杂状态
线程角色主从模式对等模式资源控制多阶段
典型场景启动准备、任务分片并行计算连接池、限流多阶段任务

并发同步工具选择

需要等待其他线程完成?

需要重复使用?

考虑Semaphore

使用CountDownLatch

线程需要互相等待?

使用CyclicBarrier

需要多阶段复杂同步?

使用Phaser

考虑CyclicBarrier或自定义

场景: 启动准备/任务分片

场景: 并行计算

场景: 资源池/限流

场景: 复杂工作流

二、CountDownLatch 工作原理深度剖析

2.1 内部实现机制

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * CountDownLatch 内部 AQS 实现解析
 * 
 * CountDownLatch 内部使用 AbstractQueuedSynchronizer (AQS) 实现,
 * 这是一个基于 CLH 队列锁的框架。
 */
public class CountDownLatchInternal {

    // 简化版 AQS 实现,展示 CountDownLatch 核心逻辑
    static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;
        
        Sync(int count) {
            setState(count);  // 使用 AQS 的 state 存储计数器
        }
        
        int getCount() {
            return getState();
        }
        
        /**
         * 尝试获取共享锁
         * 当 state == 0 时返回 1,表示获取成功
         * 否则返回 -1,表示需要加入等待队列
         */
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }
        
        /**
         * 尝试释放共享锁(countDown 操作)
         * 通过 CAS 递减 state,当 state 减到 0 时返回 true
         */
        protected boolean tryReleaseShared(int releases) {
            // 自旋 CAS 操作
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;  // 计数器已为 0,无需操作
                int nextc = c - 1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;  // 返回是否减到 0
            }
        }
    }
    
    /**
     * 完整工作流程演示
     */
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== CountDownLatch 内部工作流程 ===");
        System.out.println("1. 初始化: state = N (N > 0)");
        System.out.println("2. await(): 调用 tryAcquireShared,如果 state != 0,线程进入等待队列");
        System.out.println("3. countDown(): 调用 tryReleaseShared,CAS 递减 state");
        System.out.println("4. 当 state 减到 0 时,唤醒所有等待线程");
        System.out.println("5. 被唤醒的线程从 await() 返回,继续执行");
        
        // 实际使用示例
        final int THREAD_COUNT = 3;
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
        
        System.out.println("\n实际演示:");
        System.out.println("初始化 CountDownLatch,计数器 = " + THREAD_COUNT);
        
        for (int i = 0; i < THREAD_COUNT; i++) {
            final int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("线程 " + threadId + " 开始工作");
                    Thread.sleep(1000);  // 模拟工作
                    System.out.println("线程 " + threadId + " 完成工作,调用 countDown()");
                    latch.countDown();
                    System.out.println("线程 " + threadId + " countDown 后,当前计数: " + (THREAD_COUNT - threadId - 1));
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
        }
        
        System.out.println("\n主线程调用 await(),等待所有线程完成...");
        latch.await();
        System.out.println("所有线程完成,主线程继续执行");
    }
}

2.2 工作流程详解

开始

创建CountDownLatch
初始化计数器N

启动工作线程

主线程调用await

检查计数器state

state == 0?

立即返回,继续执行

线程进入等待队列
进入阻塞状态

工作线程执行任务

任务完成,调用countDown

CAS操作递减state

state == 0?

返回,线程结束

唤醒所有等待线程

等待线程从await返回

主线程继续执行

其他工作线程继续执行

三、核心 API 详解与示例

3.1 构造函数

/**
 * CountDownLatch 构造函数详解
 */
public class ConstructorDemo {
    
    public static void main(String[] args) {
        // 示例 1: 基本用法
        System.out.println("=== 构造函数示例 ===");
        
        // 创建 CountDownLatch,指定初始计数值
        int initialCount = 5;
        CountDownLatch latch1 = new CountDownLatch(initialCount);
        System.out.println("创建 CountDownLatch,初始计数: " + initialCount);
        
        // 示例 2: 边界条件测试
        testBoundaryConditions();
        
        // 示例 3: 实际应用场景
        demonstrateRealWorldUsage();
    }
    
    private static void testBoundaryConditions() {
        System.out.println("\n=== 边界条件测试 ===");
        
        try {
            // 测试 1: 计数为 0
            CountDownLatch zeroLatch = new CountDownLatch(0);
            System.out.println("创建计数为 0 的 latch");
            zeroLatch.await();  // 应该立即返回
            System.out.println("计数为 0 的 latch await() 立即返回");
            
            // 测试 2: 计数为负数(应该抛出异常)
            try {
                CountDownLatch negativeLatch = new CountDownLatch(-1);
                System.out.println("ERROR: 应该抛出 IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                System.out.println("正确捕获 IllegalArgumentException: " + e.getMessage());
            }
            
            // 测试 3: 大计数
            int largeCount = 10000;
            CountDownLatch largeLatch = new CountDownLatch(largeCount);
            System.out.println("创建大计数 latch: " + largeCount);
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    private static void demonstrateRealWorldUsage() {
        System.out.println("\n=== 实际应用场景演示 ===");
        
        // 场景: 并行加载多个模块,主线程等待所有模块加载完成
        String[] modules = {"用户模块", "订单模块", "支付模块", "库存模块", "日志模块"};
        CountDownLatch moduleLatch = new CountDownLatch(modules.length);
        
        System.out.println("开始并行加载 " + modules.length + " 个模块:");
        
        for (int i = 0; i < modules.length; i++) {
            final String moduleName = modules[i];
            new Thread(() -> {
                try {
                    // 模拟模块加载时间
                    long loadTime = (long) (Math.random() * 2000) + 500;
                    Thread.sleep(loadTime);
                    
                    System.out.println("✓ " + moduleName + " 加载完成 (" + loadTime + "ms)");
                    moduleLatch.countDown();
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    System.out.println("✗ " + moduleName + " 加载被中断");
                    moduleLatch.countDown();  // 确保减少计数
                }
            }, "ModuleLoader-" + moduleName).start();
        }
        
        try {
            System.out.println("\n主线程等待所有模块加载完成...");
            long startWait = System.currentTimeMillis();
            moduleLatch.await();
            long endWait = System.currentTimeMillis();
            
            System.out.println("\n✅ 所有模块加载完成!");
            System.out.println("等待时间: " + (endWait - startWait) + "ms");
            System.out.println("应用程序启动完成,可以接收请求");
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("主线程等待被中断");
        }
    }
}

3.2 await() 方法详解

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * await() 方法深度解析
 * 
 * CountDownLatch 提供了多种 await 方法:
 * 1. await(): 无限期等待
 * 2. await(long timeout, TimeUnit unit): 超时等待
 * 3. 组合使用模式
 */
public class AwaitMethodsDemo {
    
    public static void main(String[] args) {
        System.out.println("=== await() 方法详解 ===");
        
        // 演示 1: 基本 await()
        demonstrateBasicAwait();
        
        // 演示 2: 超时 await()
        demonstrateTimeoutAwait();
        
        // 演示 3: 多个线程同时 await()
        demonstrateMultipleAwait();
        
        // 演示 4: 中断处理
        demonstrateInterruption();
    }
    
    private static void demonstrateBasicAwait() {
        System.out.println("\n--- 演示 1: 基本 await() ---");
        
        CountDownLatch latch = new CountDownLatch(2);
        
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("线程A 完成任务,countDown");
                latch.countDown();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
        
        new Thread(() -> {
            try {
                Thread.sleep(1500);
                System.out.println("线程B 完成任务,countDown");
                latch.countDown();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
        
        try {
            System.out.println("主线程调用 await(),开始等待...");
            long start = System.currentTimeMillis();
            latch.await();
            long end = System.currentTimeMillis();
            
            System.out.println("主线程等待结束,耗时: " + (end - start) + "ms");
            System.out.println("所有任务完成,继续执行主流程");
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("主线程等待被中断");
        }
    }
    
    private static void demonstrateTimeoutAwait() {
        System.out.println("\n--- 演示 2: 超时 await() ---");
        
        CountDownLatch latch = new CountDownLatch(3);
        
        // 启动两个线程,但第三个永远不会启动(模拟超时场景)
        for (int i = 1; i <= 2; i++) {
            final int id = i;
            new Thread(() -> {
                try {
                    Thread.sleep(id * 1000);
                    System.out.println("任务" + id + " 完成");
                    latch.countDown();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
        }
        
        try {
            System.out.println("主线程调用 await(2500ms),带超时等待...");
            long start = System.currentTimeMillis();
            boolean completed = latch.await(2500, TimeUnit.MILLISECONDS);
            long end = System.currentTimeMillis();
            
            if (completed) {
                System.out.println("✅ 所有任务在规定时间内完成");
            } else {
                System.out.println("⏰ 等待超时,仍有 " + latch.getCount() + " 个任务未完成");
            }
            System.out.println("实际等待时间: " + (end - start) + "ms");
            
            // 即使超时,也可以继续执行(但可能状态不完整)
            System.out.println("继续执行后续逻辑(可能基于不完整状态)");
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("等待被中断");
        }
    }
    
    private static void demonstrateMultipleAwait() {
        System.out.println("\n--- 演示 3: 多个线程同时 await() ---");
        
        final int WAITER_COUNT = 5;
        final int TASK_COUNT = 3;
        
        CountDownLatch startLatch = new CountDownLatch(1);  // 统一开始
        CountDownLatch completionLatch = new CountDownLatch(TASK_COUNT);  // 任务完成
        
        AtomicInteger waitersReady = new AtomicInteger(0);
        
        // 创建多个等待线程
        for (int i = 0; i < WAITER_COUNT; i++) {
            final int waiterId = i;
            new Thread(() -> {
                try {
                    waitersReady.incrementAndGet();
                    System.out.println("等待线程 " + waiterId + " 准备就绪,调用 await()");
                    
                    startLatch.await();  // 等待开始信号
                    
                    System.out.println("等待线程 " + waiterId + " 被唤醒,开始工作...");
                    Thread.sleep(500);  // 模拟工作
                    
                    completionLatch.countDown();  // 完成任务
                    System.out.println("等待线程 " + waiterId + " 完成任务");
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
        }
        
        // 等待所有等待线程就绪
        while (waitersReady.get() < WAITER_COUNT) {
            Thread.yield();
        }
        
        try {
            Thread.sleep(1000);  // 给线程一些时间进入等待状态
            System.out.println("\n所有 " + WAITER_COUNT + " 个等待线程已进入 await 状态");
            System.out.println("主线程释放开始门闩...");
            
            startLatch.countDown();  // 释放所有等待线程
            
            System.out.println("主线程等待所有任务完成...");
            completionLatch.await();
            
            System.out.println("\n✅ 所有 " + WAITER_COUNT + " 个线程都完成了工作");
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    private static void demonstrateInterruption() {
        System.out.println("\n--- 演示 4: 中断处理 ---");
        
        CountDownLatch latch = new CountDownLatch(2);
        
        Thread waitingThread = new Thread(() -> {
            try {
                System.out.println("等待线程: 调用 await()");
                latch.await();
                System.out.println("等待线程: await() 返回,继续执行");
            } catch (InterruptedException e) {
                System.out.println("等待线程: 在 await() 中被中断,中断状态: " + 
                                 Thread.currentThread().isInterrupted());
                Thread.currentThread().interrupt();  // 恢复中断状态
            }
        });
        
        waitingThread.start();
        
        try {
            // 给等待线程时间进入等待状态
            Thread.sleep(100);
            
            System.out.println("主线程: 中断等待线程");
            waitingThread.interrupt();
            
            // 等待线程结束
            waitingThread.join(1000);
            
            // 测试 latch 是否还能使用
            System.out.println("\n中断后 latch 状态:");
            System.out.println("当前计数: " + latch.getCount());
            System.out.println("尝试 countDown...");
            latch.countDown();
            System.out.println("countDown 后计数: " + latch.getCount());
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

3.3 countDown() 方法详解

import java.util.concurrent.atomic.AtomicLong;

/**
 * countDown() 方法深度解析
 * 
 * 关键特性:
 * 1. 线程安全:使用 CAS 操作保证线程安全
 * 2. 幂等性:计数为 0 后多次调用无效果
 * 3. 无阻塞:立即返回,不会阻塞调用线程
 */
public class CountDownMethodDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== countDown() 方法详解 ===");
        
        // 演示 1: 基本 countDown()
        demonstrateBasicCountDown();
        
        // 演示 2: 多线程并发 countDown()
        demonstrateConcurrentCountDown();
        
        // 演示 3: 计数为 0 后的行为
        demonstrateZeroCountBehavior();
        
        // 演示 4: countDown() 的性能特性
        demonstratePerformance();
    }
    
    private static void demonstrateBasicCountDown() {
        System.out.println("\n--- 演示 1: 基本 countDown() ---");
        
        CountDownLatch latch = new CountDownLatch(3);
        
        System.out.println("初始状态:");
        System.out.println("  计数器: " + latch.getCount());
        System.out.println("  是否归零: " + (latch.getCount() == 0));
        
        System.out.println("\n执行 countDown() 1:");
        latch.countDown();
        System.out.println("  计数器: " + latch.getCount());
        
        System.out.println("执行 countDown() 2:");
        latch.countDown();
        System.out.println("  计数器: " + latch.getCount());
        
        System.out.println("执行 countDown() 3:");
        latch.countDown();
        System.out.println("  计数器: " + latch.getCount());
        System.out.println("  是否归零: " + (latch.getCount() == 0));
        
        System.out.println("\n尝试在归零后 await():");
        try {
            latch.await();  // 应该立即返回
            System.out.println("  await() 立即返回");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    private static void demonstrateConcurrentCountDown() throws InterruptedException {
        System.out.println("\n--- 演示 2: 多线程并发 countDown() ---");
        
        final int THREAD_COUNT = 100;
        final int INITIAL_COUNT = THREAD_COUNT;
        
        CountDownLatch latch = new CountDownLatch(INITIAL_COUNT);
        AtomicLong completedThreads = new AtomicLong(0);
        
        System.out.println("启动 " + THREAD_COUNT + " 个线程并发执行 countDown()");
        System.out.println("初始计数: " + latch.getCount());
        
        // 启动多个线程同时执行 countDown
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            final int threadId = i;
            threads[i] = new Thread(() -> {
                try {
                    // 随机睡眠,模拟不同的执行时间
                    Thread.sleep((long) (Math.random() * 100));
                    
                    long before = latch.getCount();
                    latch.countDown();
                    long after = latch.getCount();
                    
                    completedThreads.incrementAndGet();
                    
                    System.out.printf("线程 %03d: 计数 %d -> %d%n", 
                                     threadId, before, after);
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
            threads[i].start();
        }
        
        // 等待所有线程启动
        for (Thread thread : threads) {
            thread.join();
        }
        
        System.out.println("\n最终状态:");
        System.out.println("  完成 countDown 的线程数: " + completedThreads.get());
        System.out.println("  最终计数器值: " + latch.getCount());
        System.out.println("  计数器是否归零: " + (latch.getCount() == 0));
        
        // 验证线程安全性
        if (completedThreads.get() == THREAD_COUNT && latch.getCount() == 0) {
            System.out.println("✅ 并发 countDown() 测试通过:线程安全");
        } else {
            System.out.println("❌ 并发 countDown() 测试失败");
        }
    }
    
    private static void demonstrateZeroCountBehavior() {
        System.out.println("\n--- 演示 3: 计数为 0 后的行为 ---");
        
        CountDownLatch latch = new CountDownLatch(1);
        
        System.out.println("初始状态: 计数 = " + latch.getCount());
        
        // 第一次 countDown,计数归零
        System.out.println("执行 countDown() 1:");
        latch.countDown();
        System.out.println("  计数: " + latch.getCount());
        
        // 第二次 countDown,计数已为 0
        System.out.println("执行 countDown() 2 (计数已为 0):");
        latch.countDown();
        System.out.println("  计数: " + latch.getCount());
        
        // 第三次 countDown,计数仍为 0
        System.out.println("执行 countDown() 3 (计数已为 0):");
        latch.countDown();
        System.out.println("  计数: " + latch.getCount());
        
        System.out.println("\n结论: countDown() 在计数为 0 后调用是安全的,但无实际效果");
        
        // 测试 await() 在计数归零后的行为
        System.out.println("\n测试计数归零后 await() 的行为:");
        try {
            System.out.println("  调用 await()...");
            long start = System.currentTimeMillis();
            latch.await();
            long end = System.currentTimeMillis();
            System.out.println("  await() 立即返回,耗时: " + (end - start) + "ms");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    private static void demonstratePerformance() {
        System.out.println("\n--- 演示 4: countDown() 性能特性 ---");
        
        final int ITERATIONS = 1000000;  // 100万次
        final int LATCH_COUNT = 1000000;
        
        System.out.println("性能测试: " + ITERATIONS + " 次 countDown() 调用");
        
        // 测试 1: 单个线程连续调用
        System.out.println("\n测试 1: 单个线程连续调用");
        CountDownLatch latch1 = new CountDownLatch(LATCH_COUNT);
        
        long start1 = System.currentTimeMillis();
        for (int i = 0; i < ITERATIONS; i++) {
            latch1.countDown();
        }
        long end1 = System.currentTimeMillis();
        
        System.out.println("  耗时: " + (end1 - start1) + "ms");
        System.out.println("  平均每次调用: " + 
                          ((double)(end1 - start1) / ITERATIONS * 1000000) + "ns");
        
        // 测试 2: 多线程并发调用
        System.out.println("\n测试 2: 多线程并发调用");
        final int THREAD_COUNT = 10;
        final int COUNT_PER_THREAD = ITERATIONS / THREAD_COUNT;
        
        CountDownLatch latch2 = new CountDownLatch(ITERATIONS);
        CountDownLatch startLatch = new CountDownLatch(1);
        CountDownLatch finishLatch = new CountDownLatch(THREAD_COUNT);
        
        Thread[] threads = new Thread[THREAD_COUNT];
        
        long start2 = System.currentTimeMillis();
        
        for (int t = 0; t < THREAD_COUNT; t++) {
            final int threadId = t;
            threads[t] = new Thread(() -> {
                try {
                    startLatch.await();  // 等待开始信号
                    
                    for (int i = 0; i < COUNT_PER_THREAD; i++) {
                        latch2.countDown();
                    }
                    
                    finishLatch.countDown();
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
            threads[t].start();
        }
        
        // 所有线程准备就绪后同时开始
        startLatch.countDown();
        
        try {
            finishLatch.await();  // 等待所有线程完成
            long end2 = System.currentTimeMillis();
            
            System.out.println("  耗时: " + (end2 - start2) + "ms");
            System.out.println("  平均每次调用: " + 
                              ((double)(end2 - start2) / ITERATIONS * 1000000) + "ns");
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        System.out.println("\n性能结论:");
        System.out.println("1. countDown() 是非常轻量级的操作");
        System.out.println("2. 多线程并发调用有很好的扩展性");
        System.out.println("3. 在计数归零后调用几乎无开销");
    }
}

3.4 getCount() 方法详解

/**
 * getCount() 方法详解
 * 
 * getCount() 返回当前的计数值,常用于调试和状态监控。
 * 注意:getCount() 的返回值只是一个快照,可能立即过时。
 */
public class GetCountMethodDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== getCount() 方法详解 ===");
        
        // 演示 1: 基本使用
        demonstrateBasicUsage();
        
        // 演示 2: 监控和调试
        demonstrateMonitoring();
        
        // 演示 3: 竞态条件演示
        demonstrateRaceCondition();
        
        // 演示 4: 实际应用场景
        demonstrateRealWorldUsage();
    }
    
    private static void demonstrateBasicUsage() {
        System.out.println("\n--- 演示 1: 基本使用 ---");
        
        CountDownLatch latch = new CountDownLatch(5);
        
        System.out.println("初始状态:");
        System.out.println("  getCount() = " + latch.getCount());
        
        System.out.println("\n执行 countDown() 后:");
        latch.countDown();
        System.out.println("  getCount() = " + latch.getCount());
        
        latch.countDown();
        System.out.println("  getCount() = " + latch.getCount());
        
        latch.countDown();
        latch.countDown();
        latch.countDown();
        System.out.println("  执行3次 countDown() 后:");
        System.out.println("  getCount() = " + latch.getCount());
        
        System.out.println("\n重要提示:");
        System.out.println("1. getCount() 返回的是调用瞬间的快照值");
        System.out.println("2. 在多线程环境中,返回值可能立即过时");
        System.out.println("3. 不要基于 getCount() 的返回值做业务决策");
    }
    
    private static void demonstrateMonitoring() throws InterruptedException {
        System.out.println("\n--- 演示 2: 监控和调试 ---");
        
        final int TASK_COUNT = 10;
        CountDownLatch latch = new CountDownLatch(TASK_COUNT);
        
        System.out.println("启动 " + TASK_COUNT + " 个任务");
        System.out.println("初始计数: " + latch.getCount());
        
        // 启动监控线程
        Thread monitorThread = new Thread(() -> {
            try {
                while (latch.getCount() > 0) {
                    System.out.printf("监控: 剩余任务数 = %d%n", latch.getCount());
                    Thread.sleep(200);  // 每200ms监控一次
                }
                System.out.println("监控: 所有任务完成!");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        monitorThread.setDaemon(true);
        monitorThread.start();
        
        // 启动工作线程
        for (int i = 0; i < TASK_COUNT; i++) {
            final int taskId = i;
            new Thread(() -> {
                try {
                    // 模拟任务执行时间
                    long duration = (long) (Math.random() * 1000) + 500;
                    Thread.sleep(duration);
                    
                    latch.countDown();
                    System.out.printf("任务 %d 完成,耗时 %dms%n", taskId, duration);
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
        }
        
        latch.await();
        System.out.println("\n主线程: 所有任务完成确认");
        
        // 给监控线程一点时间输出最后一条信息
        Thread.sleep(300);
    }
    
    private static void demonstrateRaceCondition() throws InterruptedException {
        System.out.println("\n--- 演示 3: 竞态条件演示 ---");
        
        final int THREAD_COUNT = 50;
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
        
        System.out.println("演示 getCount() 的竞态条件");
        System.out.println("启动 " + THREAD_COUNT + " 个线程快速执行 countDown()");
        
        // 创建快速执行的线程
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            final int threadId = i;
            threads[i] = new Thread(() -> {
                // 尽可能快地执行 countDown
                latch.countDown();
            });
        }
        
        // 同时启动所有线程
        for (Thread thread : threads) {
            thread.start();
        }
        
        // 在主线程中连续调用 getCount()
        System.out.println("\n主线程连续调用 getCount():");
        for (int i = 0; i < 20; i++) {
            long count = latch.getCount();
            System.out.printf("  getCount() 调用 %2d: 计数 = %2d%n", i + 1, count);
            if (count == 0) {
                System.out.println("  注意: 计数已归零,但其他线程可能仍在运行");
            }
            Thread.yield();  // 让出CPU,增加竞态条件概率
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        
        System.out.println("\n最终 getCount(): " + latch.getCount());
        System.out.println("\n竞态条件总结:");
        System.out.println("1. getCount() 返回的是瞬时值");
        System.out.println("2. 在调用 getCount() 和实际使用返回值之间,状态可能已改变");
        System.out.println("3. 适合用于监控和调试,不适合用于同步控制");
    }
    
    private static void demonstrateRealWorldUsage() {
        System.out.println("\n--- 演示 4: 实际应用场景 ---");
        
        // 场景: 批量处理任务,显示进度
        final int BATCH_SIZE = 100;
        CountDownLatch latch = new CountDownLatch(BATCH_SIZE);
        
        System.out.println("批量处理 " + BATCH_SIZE + " 个任务");
        System.out.println("显示处理进度:\n");
        
        // 进度显示线程
        new Thread(() -> {
            try {
                long total = BATCH_SIZE;
                while (true) {
                    long remaining = latch.getCount();
                    long completed = total - remaining;
                    
                    // 计算进度百分比
                    double percent = (double) completed / total * 100;
                    
                    // 显示进度条
                    int barWidth = 50;
                    int progress = (int) (barWidth * completed / total);
                    
                    System.out.printf("\r进度: [%-" + barWidth + "s] %6.2f%% (%d/%d)", 
                                     "=".repeat(progress), percent, completed, total);
                    
                    if (remaining == 0) {
                        System.out.println("\n\n✅ 批量处理完成!");
                        break;
                    }
                    
                    Thread.sleep(100);  // 每100ms更新一次进度
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
        
        // 模拟批量处理任务
        for (int i = 0; i < BATCH_SIZE; i++) {
            final int taskId = i;
            new Thread(() -> {
                try {
                    // 模拟任务处理时间
                    Thread.sleep((long) (Math.random() * 100));
                    latch.countDown();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    latch.countDown();  // 确保计数减少
                }
            }).start();
        }
        
        try {
            latch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

四、高级应用场景与实战

4.1 复杂并发模式实现

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * CountDownLatch 高级应用场景
 * 
 * 1. 并行任务分片与聚合
 * 2. 多阶段工作流
 * 3. 资源初始化协调
 * 4. 测试并发场景
 */
public class AdvancedUsageDemo {
    
    /**
     * 场景 1: 并行计算 Map-Reduce 模式
     */
    static class ParallelMapReduce {
        
        public static void main(String[] args) throws InterruptedException {
            System.out.println("=== 场景 1: 并行 Map-Reduce ===");
            
            // 模拟数据
            List<Integer> data = new ArrayList<>();
            for (int i = 1; i <= 100; i++) {
                data.add(i);
            }
            
            // 将数据分成4个分片
            int sliceCount = 4;
            int sliceSize = data.size() / sliceCount;
            
            CountDownLatch mapLatch = new CountDownLatch(sliceCount);
            List<Future<Integer>> results = new ArrayList<>();
            ExecutorService executor = Executors.newFixedThreadPool(sliceCount);
            
            System.out.println("开始并行 Map 阶段...");
            long startTime = System.currentTimeMillis();
            
            // Map 阶段:并行处理每个分片
            for (int i = 0; i < sliceCount; i++) {
                final int sliceIndex = i;
                final int fromIndex = i * sliceSize;
                final int toIndex = (i == sliceCount - 1) ? data.size() : (i + 1) * sliceSize;
                
                Callable<Integer> task = () -> {
                    try {
                        // 模拟计算密集型任务
                        int sum = 0;
                        for (int j = fromIndex; j < toIndex; j++) {
                            sum += data.get(j);
                            // 模拟处理时间
                            Thread.sleep(1);
                        }
                        System.out.printf("分片 %d 计算完成: sum = %d%n", sliceIndex, sum);
                        return sum;
                    } finally {
                        mapLatch.countDown();
                    }
                };
                
                results.add(executor.submit(task));
            }
            
            // 等待所有 Map 任务完成
            mapLatch.await();
            System.out.println("Map 阶段完成,开始 Reduce 阶段...");
            
            // Reduce 阶段:聚合结果
            int finalResult = 0;
            for (Future<Integer> future : results) {
                try {
                    finalResult += future.get();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
            
            long endTime = System.currentTimeMillis();
            
            System.out.println("最终结果: " + finalResult);
            System.out.println("总耗时: " + (endTime - startTime) + "ms");
            
            // 验证结果
            int expected = data.stream().mapToInt(Integer::intValue).sum();
            System.out.println("预期结果: " + expected);
            System.out.println("结果验证: " + (finalResult == expected ? "✅ 正确" : "❌ 错误"));
            
            executor.shutdown();
        }
    }
    
    /**
     * 场景 2: 多阶段工作流协调
     */
    static class MultiStageWorkflow {
        
        public static void main(String[] args) throws InterruptedException {
            System.out.println("\n=== 场景 2: 多阶段工作流 ===");
            
            // 定义三个阶段
            CountDownLatch stage1Latch = new CountDownLatch(3);  // 数据加载
            CountDownLatch stage2Latch = new CountDownLatch(2);  // 数据处理
            CountDownLatch stage3Latch = new CountDownLatch(1);  // 结果汇总
            
            System.out.println("开始三阶段工作流执行...\n");
            
            // 阶段1:数据加载
            System.out.println("【阶段1】数据加载(3个并行任务)");
            for (int i = 1; i <= 3; i++) {
                final int taskId = i;
                new Thread(() -> {
                    try {
                        System.out.printf("  数据加载任务 %d 开始...%n", taskId);
                        Thread.sleep(500 + taskId * 100);
                        System.out.printf("  ✓ 数据加载任务 %d 完成%n", taskId);
                        stage1Latch.countDown();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }).start();
            }
            
            // 阶段2:数据处理(等待阶段1完成后开始)
            new Thread(() -> {
                try {
                    stage1Latch.await();
                    System.out.println("\n【阶段2】数据处理(2个并行任务)");
                    
                    CountDownLatch processLatch = new CountDownLatch(2);
                    
                    for (int i = 1; i <= 2; i++) {
                        final int taskId = i;
                        new Thread(() -> {
                            try {
                                System.out.printf("  数据处理任务 %d 开始...%n", taskId);
                                Thread.sleep(800 + taskId * 100);
                                System.out.printf("  ✓ 数据处理任务 %d 完成%n", taskId);
                                processLatch.countDown();
                            } catch (InterruptedException e) {
                                Thread.currentThread().interrupt();
                            }
                        }).start();
                    }
                    
                    processLatch.await();
                    System.out.println("  → 阶段2完成,触发阶段3");
                    stage2Latch.countDown();
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
            
            // 阶段3:结果汇总(等待阶段2完成后开始)
            new Thread(() -> {
                try {
                    stage2Latch.await();
                    System.out.println("\n【阶段3】结果汇总");
                    System.out.println("  开始汇总所有处理结果...");
                    Thread.sleep(1000);
                    System.out.println("  ✓ 结果汇总完成");
                    stage3Latch.countDown();
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
            
            // 主线程等待整个工作流完成
            stage3Latch.await();
            System.out.println("\n🎉 整个工作流执行完成!");
        }
    }
    
    /**
     * 场景 3: 服务启动协调
     */
    static class ServiceInitializationCoordinator {
        
        static class Service {
            private final String name;
            private final int initTime;
            private volatile boolean initialized = false;
            
            public Service(String name, int initTime) {
                this.name = name;
                this.initTime = initTime;
            }
            
            public void initialize(CountDownLatch latch) {
                new Thread(() -> {
                    try {
                        System.out.printf("服务 '%s' 开始初始化(预计 %dms)...%n", 
                                         name, initTime);
                        Thread.sleep(initTime);
                        initialized = true;
                        System.out.printf("✅ 服务 '%s' 初始化完成%n", name);
                        latch.countDown();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        System.out.printf("❌ 服务 '%s' 初始化被中断%n", name);
                        latch.countDown();  // 确保计数减少
                    }
                }).start();
            }
            
            public boolean isInitialized() {
                return initialized;
            }
        }
        
        public static void main(String[] args) throws InterruptedException {
            System.out.println("\n=== 场景 3: 服务启动协调 ===");
            
            // 定义需要初始化的服务
            Service[] services = {
                new Service("数据库连接池", 2000),
                new Service("Redis缓存", 1500),
                new Service("消息队列", 2500),
                new Service("配置中心", 800),
                new Service("监控系统", 1200)
            };
            
            CountDownLatch initLatch = new CountDownLatch(services.length);
            
            System.out.println("开始并行初始化 " + services.length + " 个服务...\n");
            
            // 并行初始化所有服务
            for (Service service : services) {
                service.initialize(initLatch);
            }
            
            // 显示初始化进度
            new Thread(() -> {
                try {
                    while (initLatch.getCount() > 0) {
                        long remaining = initLatch.getCount();
                        System.out.printf("\r等待服务初始化... 剩余 %d 个服务 ", remaining);
                        Thread.sleep(200);
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
            
            // 等待所有服务初始化完成
            initLatch.await();
            
            System.out.println("\n\n🎉 所有服务初始化完成!");
            System.out.println("应用程序可以正常启动...");
            
            // 验证所有服务状态
            boolean allReady = true;
            for (Service service : services) {
                if (!service.isInitialized()) {
                    System.out.printf("警告: 服务 '%s' 未正确初始化%n", service.name);
                    allReady = false;
                }
            }
            
            if (allReady) {
                System.out.println("✅ 所有服务状态验证通过");
            } else {
                System.out.println("⚠️ 部分服务可能有问题,建议检查");
            }
        }
    }
    
    /**
     * 场景 4: 并发测试工具
     */
    static class ConcurrentTestHarness {
        
        public static long timeTasks(int nThreads, final Runnable task) 
                throws InterruptedException {
            
            // 起始门:确保所有线程同时开始
            final CountDownLatch startGate = new CountDownLatch(1);
            
            // 结束门:等待所有线程完成
            final CountDownLatch endGate = new CountDownLatch(nThreads);
            
            for (int i = 0; i < nThreads; i++) {
                Thread t = new Thread(() -> {
                    try {
                        // 等待开始信号
                        startGate.await();
                        try {
                            task.run();
                        } finally {
                            // 通知任务完成
                            endGate.countDown();
                        }
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                });
                t.start();
            }
            
            long start = System.nanoTime();
            
            // 释放起始门,所有线程同时开始执行
            startGate.countDown();
            
            // 等待所有线程完成
            endGate.await();
            
            long end = System.nanoTime();
            
            return end - start;
        }
        
        public static void main(String[] args) throws InterruptedException {
            System.out.println("\n=== 场景 4: 并发测试工具 ===");
            
            // 测试任务:模拟一些工作
            Runnable testTask = () -> {
                // 模拟一些计算工作
                long sum = 0;
                for (int i = 0; i < 1000000; i++) {
                    sum += i % 3;
                }
                // 模拟一些IO等待
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            };
            
            // 测试不同线程数下的性能
            int[] threadCounts = {1, 2, 4, 8, 16, 32};
            
            System.out.println("并发性能测试(每个线程执行相同任务)");
            System.out.println("线程数 | 耗时(ns) | 加速比");
            System.out.println("------|----------|------");
            
            long singleThreadTime = 0;
            
            for (int nThreads : threadCounts) {
                long duration = timeTasks(nThreads, testTask);
                
                if (nThreads == 1) {
                    singleThreadTime = duration;
                }
                
                double speedup = (double) singleThreadTime / duration;
                
                System.out.printf("%6d | %9d | %.2fx%n", 
                                 nThreads, duration, speedup);
            }
            
            System.out.println("\n测试说明:");
            System.out.println("1. 使用 CountDownLatch 确保所有线程同时开始");
            System.out.println("2. 使用 CountDownLatch 等待所有线程完成");
            System.out.println("3. 可以准确测量并发执行时间");
            System.out.println("4. 适用于性能基准测试和并发问题复现");
        }
    }
}

4.2 生产环境最佳实践

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * CountDownLatch 生产环境最佳实践
 * 
 * 包括错误处理、资源管理、性能优化等
 */
public class ProductionBestPractices {
    
    /**
     * 实践 1: 异常安全的使用模式
     */
    static class ExceptionSafePattern {
        
        public static void executeWithWorkers(int workerCount) 
                throws InterruptedException {
            
            CountDownLatch completionLatch = new CountDownLatch(workerCount);
            AtomicBoolean hasError = new AtomicBoolean(false);
            
            for (int i = 0; i < workerCount; i++) {
                final int workerId = i;
                new Thread(() -> {
                    try {
                        // 执行工作任务
                        doWork(workerId);
                        
                        // 只有成功完成才减少计数
                        if (!hasError.get()) {
                            completionLatch.countDown();
                            System.out.printf("Worker %d completed successfully%n", workerId);
                        }
                        
                    } catch (Exception e) {
                        // 发生异常,设置错误标志
                        hasError.set(true);
                        System.err.printf("Worker %d failed: %s%n", workerId, e.getMessage());
                        
                        // 立即减少计数,让主线程可以继续处理
                        while (completionLatch.getCount() > 0) {
                            completionLatch.countDown();
                        }
                    }
                }).start();
            }
            
            // 等待所有工作完成或发生错误
            completionLatch.await();
            
            if (hasError.get()) {
                System.out.println("任务执行过程中发生错误,进行错误处理...");
                handleError();
            } else {
                System.out.println("所有任务成功完成");
            }
        }
        
        private static void doWork(int workerId) throws Exception {
            // 模拟工作,随机失败
            if (Math.random() < 0.2) {
                throw new Exception("模拟的工作错误");
            }
            Thread.sleep(1000);
        }
        
        private static void handleError() {
            // 错误处理逻辑
            System.out.println("执行错误恢复操作...");
        }
    }
    
    /**
     * 实践 2: 超时与中断处理
     */
    static class TimeoutAndInterruption {
        
        public static class TaskExecutor {
            private final CountDownLatch latch;
            private final AtomicBoolean cancelled;
            
            public TaskExecutor(int taskCount) {
                this.latch = new CountDownLatch(taskCount);
                this.cancelled = new AtomicBoolean(false);
            }
            
            public void executeTask(Runnable task) {
                new Thread(() -> {
                    if (cancelled.get()) {
                        System.out.println("任务已取消,跳过执行");
                        latch.countDown();
                        return;
                    }
                    
                    try {
                        task.run();
                        System.out.println("任务执行完成");
                    } catch (Exception e) {
                        System.err.println("任务执行异常: " + e.getMessage());
                    } finally {
                        latch.countDown();
                    }
                }).start();
            }
            
            public boolean awaitCompletion(long timeout, TimeUnit unit) 
                    throws InterruptedException {
                return latch.await(timeout, unit);
            }
            
            public void cancelAll() {
                cancelled.set(true);
                // 快速释放所有等待
                while (latch.getCount() > 0) {
                    latch.countDown();
                }
            }
        }
        
        public static void main(String[] args) {
            TaskExecutor executor = new TaskExecutor(5);
            
            // 添加任务
            for (int i = 0; i < 5; i++) {
                final int taskId = i;
                executor.executeTask(() -> {
                    try {
                        Thread.sleep(2000);  // 模拟长时间任务
                        System.out.println("Task " + taskId + " finished");
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                });
            }
            
            // 监控线程:超时后取消任务
            new Thread(() -> {
                try {
                    Thread.sleep(3000);  // 3秒后超时
                    System.out.println("超时,取消所有任务");
                    executor.cancelAll();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
            
            try {
                boolean completed = executor.awaitCompletion(5, TimeUnit.SECONDS);
                if (completed) {
                    System.out.println("所有任务正常完成");
                } else {
                    System.out.println("任务执行超时或被取消");
                }
            } catch (InterruptedException e) {
                System.out.println("等待被中断");
                executor.cancelAll();
            }
        }
    }
    
    /**
     * 实践 3: 资源清理模式
     */
    static class ResourceCleanupPattern {
        
        static class ResourceManager {
            private final CountDownLatch shutdownLatch;
            private final List<AutoCloseable> resources;
            
            public ResourceManager() {
                this.shutdownLatch = new CountDownLatch(1);
                this.resources = new ArrayList<>();
            }
            
            public void addResource(AutoCloseable resource) {
                resources.add(resource);
            }
            
            public void shutdown() {
                System.out.println("开始关闭资源...");
                
                // 使用 CountDownLatch 协调资源关闭
                CountDownLatch cleanupLatch = new CountDownLatch(resources.size());
                
                for (AutoCloseable resource : resources) {
                    new Thread(() -> {
                        try {
                            resource.close();
                            System.out.println("资源关闭成功: " + resource.getClass().getSimpleName());
                        } catch (Exception e) {
                            System.err.println("资源关闭失败: " + e.getMessage());
                        } finally {
                            cleanupLatch.countDown();
                        }
                    }).start();
                }
                
                try {
                    // 等待所有资源关闭完成
                    cleanupLatch.await(10, TimeUnit.SECONDS);
                    System.out.println("所有资源关闭完成");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    System.out.println("资源关闭被中断");
                } finally {
                    // 通知主线程可以继续
                    shutdownLatch.countDown();
                }
            }
            
            public void awaitShutdown() throws InterruptedException {
                shutdownLatch.await();
            }
        }
        
        public static void main(String[] args) throws Exception {
            ResourceManager manager = new ResourceManager();
            
            // 模拟添加资源
            manager.addResource(() -> {
                System.out.println("关闭数据库连接");
                Thread.sleep(500);
            });
            
            manager.addResource(() -> {
                System.out.println("关闭网络连接");
                Thread.sleep(300);
            });
            
            manager.addResource(() -> {
                System.out.println("关闭文件句柄");
                Thread.sleep(200);
            });
            
            // 启动关闭过程
            new Thread(manager::shutdown).start();
            
            // 等待关闭完成
            manager.awaitShutdown();
            System.out.println("应用程序安全退出");
        }
    }
    
    /**
     * 实践 4: 性能监控与调试
     */
    static class PerformanceMonitoring {
        
        static class MonitoredLatch extends CountDownLatch {
            private final String name;
            private final long creationTime;
            private volatile long lastCountDownTime;
            private final AtomicLong countDownCount = new AtomicLong();
            
            public MonitoredLatch(String name, int count) {
                super(count);
                this.name = name;
                this.creationTime = System.currentTimeMillis();
                this.lastCountDownTime = creationTime;
            }
            
            @Override
            public void countDown() {
                super.countDown();
                countDownCount.incrementAndGet();
                lastCountDownTime = System.currentTimeMillis();
            }
            
            public void printStats() {
                long currentCount = getCount();
                long elapsed = System.currentTimeMillis() - creationTime;
                long timeSinceLastCountDown = System.currentTimeMillis() - lastCountDownTime;
                
                System.out.println("\n=== Latch 统计信息 ===");
                System.out.println("名称: " + name);
                System.out.println("初始计数: " + countDownCount.get() + currentCount);
                System.out.println("当前剩余计数: " + currentCount);
                System.out.println("已执行 countDown 次数: " + countDownCount.get());
                System.out.println("创建时间: " + elapsed + "ms 前");
                System.out.println("距离上次 countDown: " + timeSinceLastCountDown + "ms");
                
                if (currentCount == 0) {
                    System.out.println("状态: 已完成");
                } else if (timeSinceLastCountDown > 10000) {
                    System.out.println("警告: 超过10秒没有 countDown 活动");
                } else {
                    System.out.println("状态: 进行中");
                }
            }
        }
        
        public static void main(String[] args) throws InterruptedException {
            MonitoredLatch latch = new MonitoredLatch("数据处理门闩", 5);
            
            // 启动任务
            for (int i = 0; i < 5; i++) {
                final int taskId = i;
                new Thread(() -> {
                    try {
                        Thread.sleep(1000 + taskId * 500);
                        latch.countDown();
                        System.out.println("任务 " + taskId + " 完成");
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }).start();
            }
            
            // 监控线程
            new Thread(() -> {
                while (latch.getCount() > 0) {
                    try {
                        Thread.sleep(1000);
                        latch.printStats();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }).start();
            
            latch.await();
            System.out.println("\n最终统计:");
            latch.printStats();
        }
    }
}

五、常见问题与解决方案

5.1 典型错误与陷阱

import java.util.concurrent.atomic.AtomicInteger;

/**
 * CountDownLatch 常见错误与解决方案
 */
public class CommonPitfallsAndSolutions {
    
    /**
     * 陷阱 1: 忘记调用 countDown()
     */
    static class Pitfall1_ForgetCountDown {
        
        public static void wrongWay() throws InterruptedException {
            System.out.println("=== 陷阱 1: 忘记调用 countDown() ===");
            
            CountDownLatch latch = new CountDownLatch(3);
            
            // 只启动两个线程,但 latch 需要三个 countDown
            for (int i = 0; i < 2; i++) {
                new Thread(() -> {
                    try {
                        Thread.sleep(1000);
                        latch.countDown();  // 这里只调用两次
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }).start();
            }
            
            System.out.println("主线程等待...");
            latch.await();  // 这里会永远等待!
            System.out.println("这行永远不会执行");
        }
        
        public static void correctWay() throws InterruptedException {
            System.out.println("\n✅ 正确做法: 确保 countDown() 被调用");
            
            CountDownLatch latch = new CountDownLatch(3);
            AtomicInteger completedTasks = new AtomicInteger(0);
            
            // 使用 try-finally 确保 countDown 被调用
            for (int i = 0; i < 3; i++) {
                new Thread(() -> {
                    try {
                        // 模拟可能失败的任务
                        if (Math.random() < 0.3) {
                            throw new RuntimeException("任务执行失败");
                        }
                        Thread.sleep(1000);
                        completedTasks.incrementAndGet();
                    } catch (Exception e) {
                        System.err.println("任务异常: " + e.getMessage());
                    } finally {
                        // 确保无论成功失败都减少计数
                        latch.countDown();
                        System.out.println("countDown 被调用,剩余: " + latch.getCount());
                    }
                }).start();
            }
            
            // 设置超时,防止永久等待
            boolean completed = latch.await(5, TimeUnit.SECONDS);
            
            if (completed) {
                System.out.println("所有任务完成,成功数: " + completedTasks.get());
            } else {
                System.out.println("等待超时,剩余任务: " + latch.getCount());
            }
        }
    }
    
    /**
     * 陷阱 2: 在 countDown() 之前 await()
     */
    static class Pitfall2_AwaitBeforeCountDown {
        
        public static void wrongWay() {
            System.out.println("\n=== 陷阱 2: 线程启动顺序问题 ===");
            
            CountDownLatch latch = new CountDownLatch(1);
            
            // 先 await 再启动线程
            new Thread(() -> {
                try {
                    System.out.println("等待线程开始等待...");
                    latch.await();  // 这会阻塞
                    System.out.println("等待线程被唤醒");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
            
            // 主线程直接继续执行
            System.out.println("主线程继续执行...");
            // 忘记启动 countDown 线程!
        }
        
        public static void correctWay() throws InterruptedException {
            System.out.println("\n✅ 正确做法: 确保线程启动顺序");
            
            CountDownLatch startLatch = new CountDownLatch(1);
            CountDownLatch finishLatch = new CountDownLatch(1);
            
            // 工作线程
            Thread worker = new Thread(() -> {
                try {
                    System.out.println("工作线程: 等待开始信号...");
                    startLatch.await();  // 等待开始信号
                    
                    System.out.println("工作线程: 开始工作...");
                    Thread.sleep(1000);
                    System.out.println("工作线程: 工作完成");
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    finishLatch.countDown();  // 通知完成
                }
            });
            
            // 启动工作线程
            worker.start();
            
            // 给工作线程时间进入等待状态
            Thread.sleep(100);
            
            System.out.println("主线程: 发送开始信号");
            startLatch.countDown();  // 释放工作线程
            
            System.out.println("主线程: 等待工作完成");
            finishLatch.await();     // 等待工作完成
            
            System.out.println("主线程: 所有任务完成");
        }
    }
    
    /**
     * 陷阱 3: 错误的重用尝试
     */
    static class Pitfall3_ReuseAttempt {
        
        public static void wrongWay() throws InterruptedException {
            System.out.println("\n=== 陷阱 3: 错误的重用尝试 ===");
            
            CountDownLatch latch = new CountDownLatch(1);
            
            // 第一次使用
            new Thread(() -> {
                try {
                    Thread.sleep(500);
                    latch.countDown();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
            
            latch.await();
            System.out.println("第一次等待完成");
            
            // 错误地尝试重用
            System.out.println("尝试重用 latch...");
            
            new Thread(() -> {
                try {
                    Thread.sleep(500);
                    latch.countDown();  // 这不会生效!
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();
            
            // 这里会立即返回,但并不是因为新线程完成了
            latch.await();
            System.out.println("第二次等待完成(但可能是错误的!)");
        }
        
        public static void correctWay() throws InterruptedException {
            System.out.println("\n✅ 正确做法: 使用 CyclicBarrier 或创建新实例");
            
            // 方案1: 使用 CyclicBarrier(如果需要重用)
            System.out.println("方案1: 使用 CyclicBarrier 替代");
            
            java.util.concurrent.CyclicBarrier barrier = 
                new java.util.concurrent.CyclicBarrier(2);
            
            for (int i = 0; i < 2; i++) {  // 重用两次
                final int round = i + 1;
                new Thread(() -> {
                    try {
                        System.out.println("第" + round + "轮: 线程工作...");
                        Thread.sleep(500);
                        barrier.await();  // 等待另一个线程
                        System.out.println("第" + round + "轮: 同步完成");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }).start();
                
                Thread.sleep(100);  // 错开启动时间
            }
            
            Thread.sleep(1500);
            
            // 方案2: 每次都创建新的 CountDownLatch
            System.out.println("\n方案2: 创建新的 CountDownLatch 实例");
            
            for (int i = 0; i < 2; i++) {
                CountDownLatch newLatch = new CountDownLatch(1);
                final int round = i + 1;
                
                new Thread(() -> {
                    try {
                        System.out.println("第" + round + "轮: 新线程工作...");
                        Thread.sleep(500);
                        newLatch.countDown();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }).start();
                
                newLatch.await();
                System.out.println("第" + round + "轮: 等待完成");
            }
        }
    }
    
    /**
     * 陷阱 4: 计数不匹配
     */
    static class Pitfall4_CountMismatch {
        
        public static void wrongWay() throws InterruptedException {
            System.out.println("\n=== 陷阱 4: 计数不匹配 ===");
            
            // 动态任务列表
            List<Runnable> tasks = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
                final int taskId = i;
                tasks.add(() -> {
                    try {
                        Thread.sleep(500);
                        System.out.println("任务 " + taskId + " 完成");
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                });
            }
            
            // 错误:硬编码计数
            CountDownLatch latch = new CountDownLatch(5);  // 硬编码为5
            
            for (Runnable task : tasks) {
                new Thread(() -> {
                    task.run();
                    latch.countDown();
                }).start();
            }
            
            latch.await();  // 会永远等待额外的2个 countDown
            System.out.println("这行可能不会执行");
        }
        
        public static void correctWay() throws InterruptedException {
            System.out.println("\n✅ 正确做法: 动态计算计数");
            
            // 动态任务列表
            List<Runnable> tasks = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
                final int taskId = i;
                tasks.add(() -> {
                    try {
                        Thread.sleep(500);
                        System.out.println("任务 " + taskId + " 完成");
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                });
            }
            
            // 正确:根据任务数量动态设置计数
            CountDownLatch latch = new CountDownLatch(tasks.size());
            
            for (Runnable task : tasks) {
                new Thread(() -> {
                    try {
                        task.run();
                    } finally {
                        latch.countDown();
                    }
                }).start();
            }
            
            boolean completed = latch.await(2, TimeUnit.SECONDS);
            if (completed) {
                System.out.println("所有任务完成");
            } else {
                System.out.println("等待超时,剩余任务: " + latch.getCount());
            }
            
            // 更好的做法:使用 ExecutorService
            System.out.println("\n更好的做法: 使用 ExecutorService");
            
            ExecutorService executor = Executors.newFixedThreadPool(3);
            List<Future<?>> futures = new ArrayList<>();
            
            for (Runnable task : tasks) {
                futures.add(executor.submit(task));
            }
            
            // 等待所有任务完成
            for (Future<?> future : futures) {
                try {
                    future.get();
                } catch (ExecutionException e) {
                    System.err.println("任务执行异常: " + e.getCause().getMessage());
                }
            }
            
            System.out.println("所有任务完成(使用 ExecutorService)");
            executor.shutdown();
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        // 演示各种陷阱和解决方案
        Pitfall1_ForgetCountDown.correctWay();
        Pitfall2_AwaitBeforeCountDown.correctWay();
        Pitfall3_ReuseAttempt.correctWay();
        Pitfall4_CountMismatch.correctWay();
        
        // 注意:wrongWay() 方法可能导致死锁,这里不实际执行
        System.out.println("\n⚠️ 注意:错误的用法可能导致死锁,实际使用时要小心");
    }
}

5.2 调试技巧与工具

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.locks.LockSupport;

/**
 * CountDownLatch 调试技巧与工具
 */
public class DebuggingTechniques {
    
    /**
     * 技巧 1: 线程转储分析
     */
    static class ThreadDumpAnalyzer {
        
        public static void analyzeDeadlock() throws InterruptedException {
            System.out.println("=== 调试技巧 1: 线程转储分析 ===");
            
            CountDownLatch latch = new CountDownLatch(1);
            
            // 创建可能死锁的场景
            Thread waitingThread = new Thread(() -> {
                try {
                    System.out.println("等待线程: 开始等待 latch");
                    latch.await();  // 这会阻塞
                    System.out.println("等待线程: 被唤醒");
                } catch (InterruptedException e) {
                    System.out.println("等待线程: 被中断");
                    Thread.currentThread().interrupt();
                }
            }, "WaitingThread");
            
            waitingThread.start();
            
            // 给线程时间进入等待状态
            Thread.sleep(100);
            
            System.out.println("\n当前线程状态:");
            printThreadDump();
            
            // 模拟忘记调用 countDown
            System.out.println("\n模拟死锁场景:忘记调用 countDown()");
            System.out.println("等待 3 秒后检查线程状态...");
            
            Thread.sleep(3000);
            
            System.out.println("\n3秒后的线程状态:");
            printThreadDump();
            
            // 最后释放 latch 避免永久阻塞
            latch.countDown();
            waitingThread.join();
        }
        
        private static void printThreadDump() {
            ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
            
            // 检测死锁
            long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
            if (deadlockedThreads != null && deadlockedThreads.length > 0) {
                System.out.println("⚠️ 检测到死锁线程:");
                for (long threadId : deadlockedThreads) {
                    ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId);
                    System.out.println("  - " + threadInfo.getThreadName());
                }
            } else {
                System.out.println("未检测到死锁");
            }
            
            // 打印所有线程状态
            System.out.println("\n所有线程状态:");
            ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
            for (ThreadInfo threadInfo : threadInfos) {
                if (threadInfo.getThreadName().contains("Thread") || 
                    threadInfo.getThreadName().equals("main")) {
                    System.out.printf("  %-20s: %s%n", 
                                     threadInfo.getThreadName(),
                                     threadInfo.getThreadState());
                }
            }
        }
    }
    
    /**
     * 技巧 2: 自定义监控 Latch
     */
    static class DebuggableCountDownLatch extends CountDownLatch {
        private final String name;
        private final StackTraceElement[] creationStackTrace;
        private final List<StackTraceElement[]> awaitStackTraces = 
            Collections.synchronizedList(new ArrayList<>());
        private final List<Long> countDownTimestamps = 
            Collections.synchronizedList(new ArrayList<>());
        
        public DebuggableCountDownLatch(String name, int count) {
            super(count);
            this.name = name;
            this.creationStackTrace = Thread.currentThread().getStackTrace();
        }
        
        @Override
        public void await() throws InterruptedException {
            // 记录谁在等待
            awaitStackTraces.add(Thread.currentThread().getStackTrace());
            System.out.printf("[DEBUG] %s: 线程 '%s' 开始等待%n", 
                             name, Thread.currentThread().getName());
            
            long start = System.currentTimeMillis();
            super.await();
            long end = System.currentTimeMillis();
            
            System.out.printf("[DEBUG] %s: 线程 '%s' 等待结束,耗时 %dms%n", 
                             name, Thread.currentThread().getName(), end - start);
        }
        
        @Override
        public boolean await(long timeout, TimeUnit unit) 
                throws InterruptedException {
            awaitStackTraces.add(Thread.currentThread().getStackTrace());
            System.out.printf("[DEBUG] %s: 线程 '%s' 开始超时等待 (%d %s)%n", 
                             name, Thread.currentThread().getName(), 
                             timeout, unit);
            
            long start = System.currentTimeMillis();
            boolean result = super.await(timeout, unit);
            long end = System.currentTimeMillis();
            
            System.out.printf("[DEBUG] %s: 线程 '%s' 超时等待结束,结果=%s,耗时 %dms%n", 
                             name, Thread.currentThread().getName(), 
                             result, end - start);
            return result;
        }
        
        @Override
        public void countDown() {
            countDownTimestamps.add(System.currentTimeMillis());
            System.out.printf("[DEBUG] %s: countDown 调用,剩余计数=%d%n", 
                             name, getCount() - 1);
            super.countDown();
        }
        
        public void printDebugInfo() {
            System.out.println("\n=== " + name + " 调试信息 ===");
            System.out.println("创建位置:");
            for (int i = 2; i < Math.min(creationStackTrace.length, 6); i++) {
                System.out.println("  " + creationStackTrace[i]);
            }
            
            System.out.println("\n等待线程栈追踪 (" + awaitStackTraces.size() + " 个):");
            for (int i = 0; i < awaitStackTraces.size(); i++) {
                System.out.println("  等待 #" + (i + 1) + ":");
                StackTraceElement[] trace = awaitStackTraces.get(i);
                for (int j = 2; j < Math.min(trace.length, 5); j++) {
                    System.out.println("    " + trace[j]);
                }
            }
            
            System.out.println("\ncountDown 时间戳 (" + countDownTimestamps.size() + " 次):");
            if (!countDownTimestamps.isEmpty()) {
                long first = countDownTimestamps.get(0);
                for (int i = 0; i < countDownTimestamps.size(); i++) {
                    long timestamp = countDownTimestamps.get(i);
                    System.out.printf("  #%d: +%dms%n", 
                                     i + 1, timestamp - first);
                }
            }
            
            System.out.println("\n当前状态: 计数=" + getCount());
        }
    }
    
    /**
     * 技巧 3: 使用 JMX 监控
     */
    static class JMXMonitor {
        
        static class MonitoredService implements MonitoredServiceMBean {
            private final CountDownLatch latch;
            private final String serviceName;
            private volatile long startTime;
            private volatile long lastActivityTime;
            
            public MonitoredService(String name, int taskCount) {
                this.serviceName = name;
                this.latch = new CountDownLatch(taskCount);
                this.startTime = System.currentTimeMillis();
                this.lastActivityTime = startTime;
            }
            
            public void countDown() {
                latch.countDown();
                lastActivityTime = System.currentTimeMillis();
            }
            
            public void await() throws InterruptedException {
                latch.await();
            }
            
            // JMX 属性
            @Override
            public String getServiceName() {
                return serviceName;
            }
            
            @Override
            public long getRemainingCount() {
                return latch.getCount();
            }
            
            @Override
            public long getUptime() {
                return System.currentTimeMillis() - startTime;
            }
            
            @Override
            public long getTimeSinceLastActivity() {
                return System.currentTimeMillis() - lastActivityTime;
            }
            
            @Override
            public boolean isCompleted() {
                return latch.getCount() == 0;
            }
        }
        
        interface MonitoredServiceMBean {
            String getServiceName();
            long getRemainingCount();
            long getUptime();
            long getTimeSinceLastActivity();
            boolean isCompleted();
        }
        
        public static void main(String[] args) throws Exception {
            System.out.println("=== 调试技巧 3: JMX 监控 ===");
            
            MonitoredService service = new MonitoredService("数据处理服务", 5);
            
            // 注册 JMX MBean(简化版,实际需要完整的 JMX 注册代码)
            System.out.println("服务已创建,可通过 JMX 监控:");
            System.out.println("  服务名称: " + service.getServiceName());
            System.out.println("  初始计数: " + service.getRemainingCount());
            System.out.println("  运行时间: " + service.getUptime() + "ms");
            
            // 模拟任务执行
            for (int i = 0; i < 5; i++) {
                final int taskId = i;
                new Thread(() -> {
                    try {
                        Thread.sleep(1000 + taskId * 500);
                        service.countDown();
                        System.out.printf("任务 %d 完成,剩余计数: %d%n", 
                                         taskId, service.getRemainingCount());
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }).start();
            }
            
            // 监控线程
            new Thread(() -> {
                while (service.getRemainingCount() > 0) {
                    try {
                        Thread.sleep(1000);
                        System.out.printf("\r监控: 剩余=%d, 最后活动=%dms前", 
                                         service.getRemainingCount(),
                                         service.getTimeSinceLastActivity());
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
                System.out.println("\n监控: 服务完成");
            }).start();
            
            service.await();
            System.out.println("\n✅ 所有任务完成");
        }
    }
    
    /**
     * 技巧 4: 单元测试模式
     */
    static class UnitTestPatterns {
        
        static class LatchTestUtils {
            
            /**
             * 测试 CountDownLatch 是否正常工作的工具方法
             */
            public static boolean testLatchFunctionality(
                    int threadCount, 
                    long timeout, 
                    TimeUnit unit) throws InterruptedException {
                
                CountDownLatch latch = new CountDownLatch(threadCount);
                AtomicInteger completedCount = new AtomicInteger(0);
                
                // 启动工作线程
                for (int i = 0; i < threadCount; i++) {
                    new Thread(() -> {
                        try {
                            // 模拟工作
                            Thread.sleep(100);
                            completedCount.incrementAndGet();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        } finally {
                            latch.countDown();
                        }
                    }).start();
                }
                
                // 等待完成
                boolean completed = latch.await(timeout, unit);
                
                // 验证结果
                if (completed && completedCount.get() == threadCount) {
                    System.out.println("✅ Latch 功能测试通过");
                    return true;
                } else {
                    System.out.printf("❌ Latch 功能测试失败: completed=%s, count=%d/%d%n",
                                     completed, completedCount.get(), threadCount);
                    return false;
                }
            }
            
            /**
             * 测试超时功能
             */
            public static boolean testTimeoutFunctionality() 
                    throws InterruptedException {
                
                CountDownLatch latch = new CountDownLatch(3);
                
                // 只启动2个线程,故意制造超时
                for (int i = 0; i < 2; i++) {
                    new Thread(() -> {
                        try {
                            Thread.sleep(500);
                            latch.countDown();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }).start();
                }
                
                // 应该超时
                boolean completed = latch.await(1000, TimeUnit.MILLISECONDS);
                
                if (!completed && latch.getCount() == 1) {
                    System.out.println("✅ 超时功能测试通过");
                    return true;
                } else {
                    System.out.printf("❌ 超时功能测试失败: completed=%s, remaining=%d%n",
                                     completed, latch.getCount());
                    return false;
                }
            }
            
            /**
             * 测试中断处理
             */
            public static boolean testInterruptionHandling() 
                    throws InterruptedException {
                
                CountDownLatch latch = new CountDownLatch(1);
                AtomicBoolean wasInterrupted = new AtomicBoolean(false);
                
                Thread waitingThread = new Thread(() -> {
                    try {
                        latch.await();
                    } catch (InterruptedException e) {
                        wasInterrupted.set(true);
                        Thread.currentThread().interrupt();
                    }
                });
                
                waitingThread.start();
                
                // 给线程时间进入等待状态
                Thread.sleep(100);
                
                // 中断等待线程
                waitingThread.interrupt();
                waitingThread.join(1000);
                
                // 验证中断状态
                boolean interrupted = wasInterrupted.get() || 
                                     waitingThread.isInterrupted();
                
                if (interrupted) {
                    System.out.println("✅ 中断处理测试通过");
                    return true;
                } else {
                    System.out.println("❌ 中断处理测试失败");
                    return false;
                }
            }
        }
        
        public static void main(String[] args) throws InterruptedException {
            System.out.println("=== 调试技巧 4: 单元测试模式 ===");
            
            System.out.println("\n测试 1: 基本功能测试");
            boolean test1 = LatchTestUtils.testLatchFunctionality(5, 2000, TimeUnit.MILLISECONDS);
            
            System.out.println("\n测试 2: 超时功能测试");
            boolean test2 = LatchTestUtils.testTimeoutFunctionality();
            
            System.out.println("\n测试 3: 中断处理测试");
            boolean test3 = LatchTestUtils.testInterruptionHandling();
            
            System.out.println("\n=== 测试结果汇总 ===");
            System.out.println("测试 1 (基本功能): " + (test1 ? "✅ 通过" : "❌ 失败"));
            System.out.println("测试 2 (超时功能): " + (test2 ? "✅ 通过" : "❌ 失败"));
            System.out.println("测试 3 (中断处理): " + (test3 ? "✅ 通过" : "❌ 失败"));
            
            if (test1 && test2 && test3) {
                System.out.println("\n🎉 所有测试通过!");
            } else {
                System.out.println("\n⚠️ 部分测试失败,需要检查实现");
            }
        }
    }
    
    public static void main(String[] args) throws Exception {
        System.out.println("CountDownLatch 调试技巧演示");
        System.out.println("=" .repeat(50));
        
        // 注意:ThreadDumpAnalyzer.analyzeDeadlock() 会模拟死锁场景
        // 在实际调试时才运行
        
        System.out.println("运行调试工具演示...");
        
        // 演示可调试的 Latch
        System.out.println("\n1. 可调试的 CountDownLatch 演示:");
        DebuggableCountDownLatch debugLatch = 
            new DebuggableCountDownLatch("测试Latch", 2);
        
        new Thread(() -> {
            try {
                debugLatch.await();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "测试线程1").start();
        
        new Thread(() -> {
            try {
                Thread.sleep(500);
                debugLatch.countDown();
                Thread.sleep(500);
                debugLatch.countDown();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
        
        Thread.sleep(2000);
        debugLatch.printDebugInfo();
        
        // 演示单元测试
        System.out.println("\n2. 单元测试演示:");
        UnitTestPatterns.main(new String[0]);
    }
}

六、总结与最佳实践

6.1 CountDownLatch 核心要点总结

/**
 * CountDownLatch 使用总结
 */
public class CountDownLatchSummary {
    
    /**
     * 适用场景
     */
    static class UseCases {
        // 1. 服务启动协调
        // 2. 并行任务分片聚合
        // 3. 测试并发场景
        // 4. 多阶段工作流协调
        // 5. 资源初始化同步
    }
    
    /**
     * 最佳实践
     */
    static class BestPractices {
        // 1. 总是在 finally 块中调用 countDown()
        // 2. 设置合理的超时时间
        // 3. 根据实际任务数量动态设置计数
        // 4. 考虑使用 ExecutorService 替代手动线程管理
        // 5. 添加适当的监控和日志
    }
    
    /**
     * 常见陷阱
     */
    static class CommonPitfalls {
        // 1. 忘记调用 countDown() - 导致永久等待
        // 2. 计数不匹配 - 多计数或少计数
        // 3. 尝试重用 - CountDownLatch 是一次性的
        // 4. 没有处理中断 - await() 可能被中断
        // 5. 依赖 getCount() 做业务逻辑 - 返回值是快照
    }
    
    /**
     * 替代方案
     */
    static class Alternatives {
        // 1. CyclicBarrier - 可重用的屏障
        // 2. Phaser - 更灵活的同步器
        // 3. CompletableFuture - 更现代的异步编程
        // 4. ExecutorService.invokeAll() - 批量任务执行
    }
    
    public static void main(String[] args) {
        System.out.println("=== CountDownLatch 总结 ===");
        System.out.println("\n🎯 核心价值:");
        System.out.println("  1. 简单的线程协调机制");
        System.out.println("  2. 高效的并发控制");
        System.out.println("  3. 清晰的等待/通知语义");
        
        System.out.println("\n🔧 适用场景:");
        System.out.println("  ✅ 并行任务分片聚合");
        System.out.println("  ✅ 服务/资源初始化");
        System.out.println("  ✅ 并发测试和基准测试");
        System.out.println("  ✅ 简单的多阶段工作流");
        
        System.out.println("\n⚠️ 注意事项:");
        System.out.println("  1. 一次性使用,不能重置");
        System.out.println("  2. 确保 countDown() 被调用");
        System.out.println("  3. 考虑设置超时时间");
        System.out.println("  4. 处理可能的中断");
        
        System.out.println("\n🚀 性能特点:");
        System.out.println("  1. 基于 AQS,性能优秀");
        System.out.println("  2. countDown() 是轻量级操作");
        System.out.println("  3. 支持大量线程同时等待");
        
        System.out.println("\n📊 监控建议:");
        System.out.println("  1. 记录 latch 的创建和销毁");
        System.out.println("  2. 监控 await() 的等待时间");
        System.out.println("  3. 跟踪 countDown() 的调用频率");
        
        System.out.println("\n💡 进阶建议:");
        System.out.println("  1. 考虑使用 CompletableFuture 处理复杂异步流程");
        System.out.println("  2. 使用 ExecutorService 管理线程生命周期");
        System.out.println("  3. 为生产环境添加监控和告警");
        
        System.out.println("\n🎉 总结:");
        System.out.println("CountDownLatch 是 Java 并发工具箱中的瑞士军刀之一。");
        System.out.println("正确使用时,它可以简化复杂的线程协调问题;");
        System.out.println("错误使用时,可能导致难以调试的死锁。");
        System.out.println("理解其原理和最佳实践是成为并发编程专家的关键一步。");
    }
}

6.2 完整示例:电商订单处理系统

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

/**
 * 完整示例:电商订单处理系统
 * 演示 CountDownLatch 在实际业务场景中的应用
 */
public class ECommerceOrderSystem {
    
    /**
     * 订单处理服务
     */
    static class OrderProcessingService {
        private final ExecutorService executor;
        private final InventoryService inventoryService;
        private final PaymentService paymentService;
        private final ShippingService shippingService;
        private final NotificationService notificationService;
        
        public OrderProcessingService(int threadPoolSize) {
            this.executor = Executors.newFixedThreadPool(threadPoolSize);
            this.inventoryService = new InventoryService();
            this.paymentService = new PaymentService();
            this.shippingService = new ShippingService();
            this.notificationService = new NotificationService();
        }
        
        /**
         * 处理单个订单
         */
        public CompletableFuture<OrderResult> processOrder(Order order) {
            return CompletableFuture.supplyAsync(() -> {
                System.out.printf("开始处理订单: %s%n", order.getId());
                
                // 使用 CountDownLatch 协调并行检查
                CountDownLatch validationLatch = new CountDownLatch(2);
                AtomicBoolean inventoryAvailable = new AtomicBoolean(false);
                AtomicBoolean paymentValid = new AtomicBoolean(false);
                
                // 并行检查库存和支付
                executor.execute(() -> {
                    try {
                        boolean available = inventoryService.checkInventory(
                            order.getProductId(), order.getQuantity());
                        inventoryAvailable.set(available);
                    } finally {
                        validationLatch.countDown();
                    }
                });
                
                executor.execute(() -> {
                    try {
                        boolean valid = paymentService.validatePayment(
                            order.getPaymentMethod(), order.getAmount());
                        paymentValid.set(valid);
                    } finally {
                        validationLatch.countDown();
                    }
                });
                
                try {
                    // 等待验证完成
                    if (!validationLatch.await(5, TimeUnit.SECONDS)) {
                        return OrderResult.failed(order.getId(), 
                            "验证超时");
                    }
                    
                    // 检查验证结果
                    if (!inventoryAvailable.get()) {
                        return OrderResult.failed(order.getId(), 
                            "库存不足");
                    }
                    if (!paymentValid.get()) {
                        return OrderResult.failed(order.getId(), 
                            "支付验证失败");
                    }
                    
                    // 并行执行后续步骤
                    CountDownLatch processingLatch = new CountDownLatch(3);
                    AtomicReference<String> inventoryResult = new AtomicReference<>();
                    AtomicReference<String> paymentResult = new AtomicReference<>();
                    AtomicReference<String> shippingResult = new AtomicReference<>();
                    
                    // 扣减库存
                    executor.execute(() -> {
                        try {
                            String result = inventoryService.deductInventory(
                                order.getProductId(), order.getQuantity());
                            inventoryResult.set(result);
                        } finally {
                            processingLatch.countDown();
                        }
                    });
                    
                    // 处理支付
                    executor.execute(() -> {
                        try {
                            String result = paymentService.processPayment(
                                order.getPaymentMethod(), order.getAmount());
                            paymentResult.set(result);
                        } finally {
                            processingLatch.countDown();
                        }
                    });
                    
                    // 安排发货
                    executor.execute(() -> {
                        try {
                            String result = shippingService.arrangeShipping(
                                order.getShippingAddress());
                            shippingResult.set(result);
                        } finally {
                            processingLatch.countDown();
                        }
                    });
                    
                    // 等待所有处理完成
                    if (!processingLatch.await(10, TimeUnit.SECONDS)) {
                        return OrderResult.failed(order.getId(), 
                            "处理超时");
                    }
                    
                    // 检查处理结果
                    if (inventoryResult.get() == null || 
                        paymentResult.get() == null || 
                        shippingResult.get() == null) {
                        return OrderResult.failed(order.getId(), 
                            "处理失败");
                    }
                    
                    // 发送通知(异步,不阻塞)
                    notificationService.sendOrderConfirmation(order);
                    
                    return OrderResult.success(order.getId(), 
                        Arrays.asList(
                            inventoryResult.get(),
                            paymentResult.get(),
                            shippingResult.get()
                        ));
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return OrderResult.failed(order.getId(), "处理被中断");
                }
            }, executor);
        }
        
        /**
         * 批量处理订单
         */
        public CompletableFuture<BatchResult> processBatch(List<Order> orders) {
            System.out.printf("开始批量处理 %d 个订单%n", orders.size());
            
            CountDownLatch batchLatch = new CountDownLatch(orders.size());
            AtomicInteger successCount = new AtomicInteger(0);
            AtomicInteger failureCount = new AtomicInteger(0);
            List<OrderResult> results = 
                Collections.synchronizedList(new ArrayList<>());
            
            // 并行处理所有订单
            for (Order order : orders) {
                processOrder(order).whenComplete((result, error) -> {
                    if (error != null) {
                        failureCount.incrementAndGet();
                        results.add(OrderResult.failed(order.getId(), 
                            error.getMessage()));
                    } else if (result.isSuccess()) {
                        successCount.incrementAndGet();
                        results.add(result);
                    } else {
                        failureCount.incrementAndGet();
                        results.add(result);
                    }
                    batchLatch.countDown();
                });
            }
            
            return CompletableFuture.supplyAsync(() -> {
                try {
                    // 等待所有订单处理完成
                    batchLatch.await(30, TimeUnit.SECONDS);
                    
                    return new BatchResult(
                        orders.size(),
                        successCount.get(),
                        failureCount.get(),
                        results
                    );
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return BatchResult.failed("批量处理被中断");
                }
            });
        }
        
        public void shutdown() {
            executor.shutdown();
            try {
                if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
    
    // 模拟的服务类
    static class InventoryService {
        boolean checkInventory(String productId, int quantity) {
            // 模拟检查库存
            return Math.random() > 0.1;  // 90% 有库存
        }
        
        String deductInventory(String productId, int quantity) {
            // 模拟扣减库存
            try {
                Thread.sleep((long) (Math.random() * 100));
                return "库存扣减成功";
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return "库存扣减被中断";
            }
        }
    }
    
    static class PaymentService {
        boolean validatePayment(String method, double amount) {
            // 模拟支付验证
            return Math.random() > 0.05;  // 95% 验证通过
        }
        
        String processPayment(String method, double amount) {
            // 模拟支付处理
            try {
                Thread.sleep((long) (Math.random() * 200));
                return String.format("支付成功: %.2f via %s", amount, method);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return "支付处理被中断";
            }
        }
    }
    
    static class ShippingService {
        String arrangeShipping(String address) {
            // 模拟安排发货
            try {
                Thread.sleep((long) (Math.random() * 300));
                return "发货安排成功,地址: " + address;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return "发货安排被中断";
            }
        }
    }
    
    static class NotificationService {
        void sendOrderConfirmation(Order order) {
            // 模拟发送通知(异步)
            CompletableFuture.runAsync(() -> {
                try {
                    Thread.sleep(100);
                    System.out.printf("已发送订单确认通知: %s%n", order.getId());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
    }
    
    // 数据模型
    static class Order {
        private final String id;
        private final String productId;
        private final int quantity;
        private final String paymentMethod;
        private final double amount;
        private final String shippingAddress;
        
        public Order(String id, String productId, int quantity, 
                    String paymentMethod, double amount, String shippingAddress) {
            this.id = id;
            this.productId = productId;
            this.quantity = quantity;
            this.paymentMethod = paymentMethod;
            this.amount = amount;
            this.shippingAddress = shippingAddress;
        }
        
        // getters
        public String getId() { return id; }
        public String getProductId() { return productId; }
        public int getQuantity() { return quantity; }
        public String getPaymentMethod() { return paymentMethod; }
        public double getAmount() { return amount; }
        public String getShippingAddress() { return shippingAddress; }
    }
    
    static class OrderResult {
        private final String orderId;
        private final boolean success;
        private final String message;
        private final List<String> details;
        
        private OrderResult(String orderId, boolean success, 
                          String message, List<String> details) {
            this.orderId = orderId;
            this.success = success;
            this.message = message;
            this.details = details;
        }
        
        public static OrderResult success(String orderId, List<String> details) {
            return new OrderResult(orderId, true, "处理成功", details);
        }
        
        public static OrderResult failed(String orderId, String message) {
            return new OrderResult(orderId, false, message, null);
        }
        
        // getters
        public boolean isSuccess() { return success; }
        public String getOrderId() { return orderId; }
        public String getMessage() { return message; }
        public List<String> getDetails() { return details; }
    }
    
    static class BatchResult {
        private final int total;
        private final int success;
        private final int failure;
        private final List<OrderResult> details;
        private final String error;
        
        public BatchResult(int total, int success, int failure, 
                          List<OrderResult> details) {
            this.total = total;
            this.success = success;
            this.failure = failure;
            this.details = details;
            this.error = null;
        }
        
        public static BatchResult failed(String error) {
            return new BatchResult(0, 0, 0, null, error);
        }
        
        private BatchResult(int total, int success, int failure, 
                           List<OrderResult> details, String error) {
            this.total = total;
            this.success = success;
            this.failure = failure;
            this.details = details;
            this.error = error;
        }
        
        // getters
        public int getTotal() { return total; }
        public int getSuccess() { return success; }
        public int getFailure() { return failure; }
        public double getSuccessRate() { 
            return total > 0 ? (double) success / total * 100 : 0; 
        }
    }
    
    public static void main(String[] args) throws Exception {
        System.out.println("=== 电商订单处理系统演示 ===");
        System.out.println("演示 CountDownLatch 在实际业务中的应用\n");
        
        // 创建订单处理服务
        OrderProcessingService service = new OrderProcessingService(10);
        
        // 生成测试订单
        List<Order> orders = new ArrayList<>();
        for (int i = 1; i <= 20; i++) {
            orders.add(new Order(
                "ORD" + String.format("%04d", i),
                "PROD" + (i % 5 + 1),
                (i % 3 + 1) * 2,
                i % 2 == 0 ? "信用卡" : "支付宝",
                99.99 * (i % 4 + 1),
                "地址" + i
            ));
        }
        
        System.out.printf("生成 %d 个测试订单%n", orders.size());
        
        // 批量处理订单
        long startTime = System.currentTimeMillis();
        BatchResult result = service.processBatch(orders).get();
        long endTime = System.currentTimeMillis();
        
        // 输出结果
        System.out.println("\n=== 处理结果 ===");
        System.out.printf("总订单数: %d%n", result.getTotal());
        System.out.printf("成功: %d%n", result.getSuccess());
        System.out.printf("失败: %d%n", result.getFailure());
        System.out.printf("成功率: %.1f%%%n", result.getSuccessRate());
        System.out.printf("总耗时: %dms%n", endTime - startTime);
        
        // 输出部分订单详情
        System.out.println("\n=== 部分订单详情 ===");
        if (result.getDetails() != null) {
            int count = 0;
            for (OrderResult orderResult : result.getDetails()) {
                if (count++ < 5) {  // 只显示前5个
                    System.out.printf("订单 %s: %s%n", 
                                     orderResult.getOrderId(),
                                     orderResult.getMessage());
                }
            }
            if (result.getDetails().size() > 5) {
                System.out.printf("... 还有 %d 个订单%n", 
                                 result.getDetails().size() - 5);
            }
        }
        
        // 关闭服务
        service.shutdown();
        
        System.out.println("\n=== 系统总结 ===");
        System.out.println("CountDownLatch 在本系统中的应用:");
        System.out.println("1. 订单验证阶段: 并行检查库存和支付");
        System.out.println("2. 订单处理阶段: 并行扣库存、支付、发货");
        System.out.println("3. 批量处理阶段: 协调多个订单的并发处理");
        System.out.println("4. 超时控制: 防止单个环节阻塞整个系统");
        System.out.println("\n🎉 演示完成!");
    }
}

6.3 学习路径建议

# CountDownLatch 学习路径

## 阶段 1:基础掌握(1-2天)
1. 理解基本概念和原理
2. 掌握 await() 和 countDown() 方法
3. 完成简单的示例代码
4. 理解一次性使用的特点

## 阶段 2:应用实践(3-5天)
1. 在项目中实际应用 CountDownLatch
2. 处理各种边界条件和异常
3. 学习与 ExecutorService 结合使用
4. 实现并行任务分片模式

## 阶段 3:深入理解(1-2周)
1. 研究 AQS 实现原理
2. 理解内存模型和 happens-before
3. 学习性能优化技巧
4. 掌握调试和监控方法

## 阶段 4:扩展应用(持续学习)
1. 学习其他同步工具对比
2. 掌握 CompletableFuture 等现代并发工具
3. 理解分布式系统中的同步问题
4. 参与开源项目,学习最佳实践

## 推荐资源
1. 《Java并发编程实战》
2. Java官方文档:java.util.concurrent 包
3. 相关开源项目源码
4. 并发编程相关的技术博客和视频教程

七、总结

CountDownLatch 是 Java 并发编程中的基础且强大的工具,它的核心价值在于:

  1. 简单性:API 简单易懂,学习成本低
  2. 高效性:基于 AQS 实现,性能优秀
  3. 可靠性:经过充分测试和验证
  4. 灵活性:适用于多种并发协调场景

关键要点回顾

  • CountDownLatch 是一次性使用的,不能重置
  • 总是使用 try-finally 确保 countDown() 被调用
  • 设置合理的超时时间,避免永久等待
  • 理解其底层基于 AQS 的实现原理
  • 在生产环境中添加适当的监控和日志

进阶方向

  • 学习 CyclicBarrier 和 Phaser 等其他同步工具
  • 掌握 CompletableFuture 进行异步编程
  • 理解分布式系统中的同步协调机制
  • 参与复杂并发系统的设计和优化

掌握 CountDownLatch 不仅是学习一个工具,更是理解并发编程思想的重要一步。它在简单的 API 背后,体现了并发控制的核心原则:协调、同步和通信。

在这里插入图片描述

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北辰alk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值