JDK 8 CountDownLatch 源码详解(详细注释版)

JDK 8 CountDownLatch 源码详解(详细注释版)

1. 类定义和基本属性

public class CountDownLatch implements java.io.Serializable {
    
    // 序列化版本号
    private static final long serialVersionUID = -6424283961411517113L;

    /**
     * CountDownLatch的核心同步器
     * 继承自AbstractQueuedSynchronizer(AQS)
     * 通过AQS的state字段来表示计数器的值
     * 
     * 设计巧妙之处:
     * - 利用AQS的共享锁机制实现计数功能
     * - state=0表示计数器归零,可以通行
     * - state>0表示还有线程需要等待
     * - 通过共享模式实现多线程同时唤醒
     */
    private final Sync sync;

    /**
     * 同步器内部类
     * 继承自AbstractQueuedSynchronizer
     * 实现CountDownLatch的具体同步逻辑
     */
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        /**
         * 构造方法
         * 初始化计数器的值
         * @param count 初始计数器值
         * 
         * 初始化过程:
         * 1. 调用AQS的setState方法设置state字段
         * 2. state字段表示还需要等待的线程数量
         * 3. count必须为非负数
         */
        Sync(int count) {
            setState(count);
        }

        /**
         * 获取当前计数器值
         * @return 当前计数器值
         * 
         * 获取过程:
         * 1. 调用AQS的getState方法获取state字段
         * 2. state字段表示还需要等待的线程数量
         * 3. 返回当前计数器值
         * 
         * 时间复杂度:O(1)
         * 线程安全性:完全线程安全
         */
        int getCount() {
            return getState();
        }

        /**
         * 尝试获取共享锁
         * 这是AQS的模板方法,由子类实现
         * 
         * 获取条件:
         * - 当state=0时,表示计数器归零,可以获取锁
         * - 当state>0时,表示还有线程需要等待,不能获取锁
         * 
         * 返回值含义:
         * - 负数:获取失败
         * - 0:获取成功,但后续线程不能获取
         * - 正数:获取成功,后续线程也可以获取
         * 
         * @param acquires 获取许可数
         * @return 获取结果
         * 
         * 时间复杂度:O(1)
         * 线程安全性:完全线程安全
         */
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

        /**
         * 尝试释放共享锁
         * 这是AQS的模板方法,由子类实现
         * 
         * 释放过程:
         * 1. 减少计数器值
         * 2. 如果计数器归零,唤醒所有等待的线程
         * 3. 返回释放结果
         * 
         * 返回值含义:
         * - true:释放成功,需要唤醒等待线程
         * - false:释放失败,不需要唤醒等待线程
         * 
         * @param releases 释放许可数
         * @return 释放结果
         * 
         * 时间复杂度:O(1)
         * 线程安全性:完全原子性
         */
        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState(); // 获取当前计数器值
                if (c == 0) // 如果计数器已经归零
                    return false; // 返回false,不需要唤醒
                int nextc = c-1; // 计算新的计数器值
                if (compareAndSetState(c, nextc)) // CAS操作更新计数器
                    return nextc == 0; // 如果计数器归零,返回true需要唤醒
            }
        }
    }

    /**
     * 构造方法
     * 创建一个指定计数器值的CountDownLatch
     * @param count 初始计数器值
     * 
     * 构造过程:
     * 1. 验证count参数的有效性
     * 2. 创建Sync实例
     * 3. 初始化计数器值
     * 
     * 参数说明:
     * - count必须为非负数
     * - count=0表示门闩立即打开
     * - count>0表示需要等待指定数量的线程调用countDown()
     * 
     * @throws IllegalArgumentException 如果count为负数
     */
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

2. 核心同步方法(详细注释)

    /**
     * 等待计数器归零
     * 如果计数器尚未归零,当前线程会阻塞直到归零
     * 
     * 等待过程:
     * 1. 调用AQS的acquireSharedInterruptibly方法
     * 2. 如果计数器为0,立即返回
     * 3. 如果计数器大于0,加入等待队列并阻塞
     * 4. 被唤醒后重新检查计数器
     * 5. 重复步骤2-4直到计数器归零
     * 
     * 中断处理:
     * - 如果线程在等待过程中被中断,会抛出InterruptedException
     * - 线程可以被优雅地中止
     * 
     * 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(等待时间)
     * 线程安全性:完全线程安全
     * 
     * @throws InterruptedException 如果线程被中断
     */
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1); // 调用AQS的可中断共享获取方法
    }

    /**
     * 等待计数器归零(带超时)
     * 如果计数器尚未归零,当前线程会阻塞直到归零或超时
     * 
     * 超时处理:
     * 1. 调用AQS的tryAcquireSharedNanos方法
     * 2. 如果计数器为0,立即返回true
     * 3. 如果计数器大于0,等待指定时间
     * 4. 在等待期间可被中断
     * 5. 超时后如果计数器仍大于0,返回false
     * 6. 超时前计数器归零,返回true
     * 
     * 时间处理:
     * - 将时间单位转换为纳秒
     * - 使用高精度计时
     * - 支持任意时间单位
     * 
     * 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(等待时间)
     * 线程安全性:完全线程安全
     * 
     * @param timeout 等待时间
     * @param unit 时间单位
     * @return 如果计数器归零返回true,如果超时返回false
     * @throws InterruptedException 如果线程被中断
     */
    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    /**
     * 减少计数器值
     * 将计数器值减1,如果减到0则唤醒所有等待的线程
     * 
     * 减少过程:
     * 1. 调用AQS的releaseShared方法
     * 2. 在tryReleaseShared中减少计数器值
     * 3. 如果计数器归零,返回true
     * 4. AQS根据返回值决定是否唤醒等待线程
     * 5. 唤醒所有在等待队列中的线程
     * 
     * 原子性保证:
     * - 使用CAS操作确保减少操作的原子性
     * - 避免竞态条件
     * - 保证计数器的一致性
     * 
     * 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(高竞争)
     * 线程安全性:完全原子性
     */
    public void countDown() {
        sync.releaseShared(1); // 调用AQS的共享释放方法
    }

    /**
     * 获取当前计数器值
     * 返回当前还需要等待的线程数量
     * 
     * 查询过程:
     * 1. 调用Sync的getCount方法
     * 2. 获取AQS的state字段值
     * 3. 返回当前计数器值
     * 
     * 注意事项:
     * - 这是一个瞬时值,可能很快过时
     * - 在高并发环境下可能不是准确值
     * - 主要用于调试和监控
     * 
     * 时间复杂度:O(1)
     * 线程安全性:完全线程安全
     * 
     * @return 当前计数器值
     */
    public long getCount() {
        return sync.getCount();
    }

    /**
     * 返回对象的字符串表示
     * 重写Object类的toString方法
     * 
     * 字符串格式:
     * - 包含类名和当前计数器值
     * - 便于调试和日志输出
     * - 符合Java标准格式
     * 
     * @return 对象的字符串表示
     */
    public String toString() {
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }

3. CountDownLatch 的特点分析

核心设计理念:

/**
 * CountDownLatch的核心设计思想:
 * 
 * 1. AQS集成:
 *    - 继承AbstractQueuedSynchronizer
 *    - 复用成熟的队列管理机制
 *    - 提供完整的同步框架
 *    - 支持共享模式
 * 
 * 2. 计数器机制:
 *    - 使用AQS的state字段表示计数器
 *    - state=0表示门闩打开
 *    - state>0表示门闩关闭
 *    - 通过CAS操作保证原子性
 * 
 * 3. 共享锁语义:
 *    - 使用共享模式实现多线程同时唤醒
 *    - 多个线程可以同时通过门闩
 *    - 提高并发性能
 * 
 * 4. 一次性使用:
 *    - 计数器只能减少,不能增加
 *    - 一旦归零不能重置
 *    - 保证语义的清晰性
 * 
 * 5. 线程安全:
 *    - 所有操作都是线程安全的
 *    - 支持高并发环境
 *    - 无死锁风险
 * 
 * 6. 灵活的等待机制:
 *    - 支持无限期等待
 *    - 支持可中断等待
 *    - 支持超时等待
 *    - 提供多种等待选项
 * 
 * 7. 高效的唤醒机制:
 *    - 计数器归零时一次性唤醒所有等待线程
 *    - 避免逐个唤醒的开销
 *    - 提高唤醒效率
 * 
 * 适用场景:
 * - 主线程等待多个子线程完成
 * - 实现启动门闩
 * - 实现关闭门闩
 * - 协调多个线程的执行
 * - 实现简单的屏障机制
 */

性能特征分析:

/**
 * CountDownLatch的性能特征:
 * 
 * 时间复杂度:
 * - countDown(): O(1) 平均,O(∞) 最坏(高竞争)
 * - await(): O(1) 如果计数器为0,O(∞) 如果需要等待
 * - getCount(): O(1) 直接读取state字段
 * - await(timeout): O(1) 平均,O(∞) 最坏(等待时间)
 * 
 * 空间复杂度:
 * - O(1) 基本存储空间
 * - O(n) 等待队列空间(n为等待线程数)
 * - 每个实例固定开销很小
 * 
 * 并发特性:
 * - 完全线程安全
 * - 支持高并发读写
 * - 无锁设计(通过AQS)
 * - 共享模式提高性能
 * 
 * 与join()对比:
 * - CountDownLatch > Thread.join()(功能更丰富)
 * - CountDownLatch > Thread.join()(性能更好)
 * - CountDownLatch > Thread.join()(更灵活)
 * 
 * 与wait/notify对比:
 * - CountDownLatch > wait/notify(更简单)
 * - CountDownLatch > wait/notify(更安全)
 * - CountDownLatch > wait/notify(更高效)
 * 
 * 内存使用:
 *    - 每个实例固定开销很小
 *    - 等待线程会增加内存使用
 *    - 及时GC,避免内存泄漏
 * 
 * 适用性:
 *    - 简单的线程协调:性能优异
 *    - 复杂的同步逻辑:可能不如其他机制
 *    - 一次性的同步需求:完美匹配
 *    - 需要重置的场景:不适合
 * 
 * 性能优化:
 *    - 合理设置初始计数器值
 *    - 避免不必要的等待
 *    - 使用超时机制避免无限等待
 *    - 正确处理中断异常
 *    - 监控等待线程数量
 */

4. 使用示例和最佳实践

/**
 * 使用示例:
 * 
 * // 基本使用:主线程等待多个子线程完成
 * CountDownLatch latch = new CountDownLatch(3);
 * 
 * // 启动三个工作线程
 * for (int i = 0; i < 3; i++) {
 *     final int taskId = i;
 *     new Thread(() -> {
 *         try {
 *             // 执行任务
 *             System.out.println("Task " + taskId + " started");
 *             Thread.sleep(1000); // 模拟任务执行
 *             System.out.println("Task " + taskId + " completed");
 *         } catch (InterruptedException e) {
 *             Thread.currentThread().interrupt();
 *         } finally {
 *             latch.countDown(); // 任务完成后减少计数器
 *         }
 *     }).start();
 * }
 * 
 * // 主线程等待所有任务完成
 * try {
 *     System.out.println("Main thread waiting for tasks to complete...");
 *     latch.await(); // 等待计数器归零
 *     System.out.println("All tasks completed!");
 * } catch (InterruptedException e) {
 *     Thread.currentThread().interrupt();
 * }
 * 
 * // 带超时的等待示例
 * CountDownLatch timeoutLatch = new CountDownLatch(1);
 * 
 * Thread worker = new Thread(() -> {
 *     try {
 *         // 执行长时间任务
 *         Thread.sleep(5000);
 *         timeoutLatch.countDown();
 *     } catch (InterruptedException e) {
 *         Thread.currentThread().interrupt();
 *     }
 * });
 * worker.start();
 * 
 * try {
 *     // 等待最多2秒
 *     if (timeoutLatch.await(2, TimeUnit.SECONDS)) {
 *         System.out.println("Worker completed within timeout");
 *     } else {
 *         System.out.println("Worker timed out");
 *         worker.interrupt(); // 中断工作线程
 *     }
 * } catch (InterruptedException e) {
 *     Thread.currentThread().interrupt();
 * }
 * 
 * // 启动门闩示例
 * CountDownLatch startLatch = new CountDownLatch(1);
 * 
 * // 创建多个工作线程
 * for (int i = 0; i < 5; i++) {
 *     final int workerId = i;
 *     new Thread(() -> {
 *         try {
 *             System.out.println("Worker " + workerId + " ready");
 *             startLatch.await(); // 等待启动信号
 *             System.out.println("Worker " + workerId + " started working");
 *             // 执行实际工作
 *         } catch (InterruptedException e) {
 *             Thread.currentThread().interrupt();
 *         }
 *     }).start();
 * }
 * 
 * // 等待所有准备工作完成
 * Thread.sleep(1000);
 * System.out.println("Starting all workers...");
 * startLatch.countDown(); // 发送启动信号
 * 
 * // 关闭门闩示例
 * CountDownLatch shutdownLatch = new CountDownLatch(3);
 * 
 * // 创建服务线程
 * for (int i = 0; i < 3; i++) {
 *     final int serviceId = i;
 *     new Thread(() -> {
 *         try {
 *             System.out.println("Service " + serviceId + " started");
 *             // 服务运行
 *             while (!Thread.currentThread().isInterrupted()) {
 *                 Thread.sleep(100);
 *                 // 检查服务状态
 *             }
 *         } catch (InterruptedException e) {
 *             System.out.println("Service " + serviceId + " interrupted");
 *         } finally {
 *             shutdownLatch.countDown(); // 服务关闭后减少计数器
 *             System.out.println("Service " + serviceId + " shut down");
 *         }
 *     }).start();
 * }
 * 
 * // 关闭所有服务
 * public void shutdownServices() {
 *     System.out.println("Shutting down all services...");
 *     // 中断所有服务线程
 *     Thread.currentThread().getThreadGroup().interrupt();
 *     
 *     try {
 *         // 等待所有服务关闭
 *         if (shutdownLatch.await(10, TimeUnit.SECONDS)) {
 *             System.out.println("All services shut down successfully");
 *         } else {
 *             System.out.println("Some services failed to shut down in time");
 *         }
 *     } catch (InterruptedException e) {
 *         Thread.currentThread().interrupt();
 *     }
 * }
 * 
 * // 多阶段任务协调示例
 * class MultiStageTaskCoordinator {
 *     private final CountDownLatch stage1Latch;
 *     private final CountDownLatch stage2Latch;
 *     private final CountDownLatch completionLatch;
 *     
 *     public MultiStageTaskCoordinator(int stage1Tasks, int stage2Tasks) {
 *         this.stage1Latch = new CountDownLatch(stage1Tasks);
 *         this.stage2Latch = new CountDownLatch(stage2Tasks);
 *         this.completionLatch = new CountDownLatch(stage1Tasks + stage2Tasks);
 *     }
 *     
 *     public void executeStage1Task() {
 *         try {
 *             // 执行第一阶段任务
 *             System.out.println("Executing stage 1 task");
 *             Thread.sleep(1000);
 *         } catch (InterruptedException e) {
 *             Thread.currentThread().interrupt();
 *         } finally {
 *             stage1Latch.countDown();
 *             completionLatch.countDown();
 *         }
 *     }
 *     
 *     public void executeStage2Task() {
 *         try {
 *             // 等待第一阶段完成
 *             stage1Latch.await();
 *             // 执行第二阶段任务
 *             System.out.println("Executing stage 2 task");
 *             Thread.sleep(1000);
 *         } catch (InterruptedException e) {
 *             Thread.currentThread().interrupt();
 *         } finally {
 *             stage2Latch.countDown();
 *             completionLatch.countDown();
 *         }
 *     }
 *     
 *     public void waitForCompletion() throws InterruptedException {
 *         completionLatch.await();
 *         System.out.println("All tasks completed");
 *     }
 * }
 * 
 * 最佳实践:
 * 
 * 1. 正确使用countDown:
 *    CountDownLatch latch = new CountDownLatch(3);
 *    
 *    // 正确的做法:在finally块中调用countDown
 *    new Thread(() -> {
 *        try {
 *            // 执行任务
 *            performTask();
 *        } catch (Exception e) {
 *            // 处理异常
 *            System.err.println("Task failed: " + e.getMessage());
 *        } finally {
 *            latch.countDown(); // 必须在finally块中调用
 *        }
 *    }).start();
 *    
 *    // 错误的做法:可能忘记调用countDown
 *    // new Thread(() -> {
 *    //     performTask(); // 如果抛出异常,countDown不会被调用
 *    //     latch.countDown(); // 可能不会执行到这里
 *    // }).start();
 * 
 * 2. 合理使用await:
 *    CountDownLatch latch = new CountDownLatch(1);
 *    
 *    // 正确的做法:处理中断异常
 *    try {
 *        latch.await();
 *        System.out.println("Ready to proceed");
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt(); // 恢复中断状态
 *        System.out.println("Waiting interrupted");
 *    }
 *    
 *    // 带超时的等待
 *    try {
 *        if (latch.await(5, TimeUnit.SECONDS)) {
 *            System.out.println("Operation completed within timeout");
 *        } else {
 *            System.out.println("Operation timed out");
 *        }
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt();
 *    }
 * 
 * 3. 设置合理的计数器值:
 *    // 根据实际需要的任务数量设置
 *    int taskCount = calculateTaskCount();
 *    CountDownLatch latch = new CountDownLatch(taskCount);
 *    
 *    // 错误的做法:硬编码计数器值
 *    // CountDownLatch latch = new CountDownLatch(10); // 可能与实际任务数不符
 * 
 * 4. 避免计数器溢出:
 *    // 确保计数器值不会溢出
 *    public CountDownLatch createLatch(int count) {
 *        if (count < 0) {
 *            throw new IllegalArgumentException("Count must be non-negative");
 *        }
 *        if (count > Integer.MAX_VALUE / 2) {
 *            System.out.println("Warning: Large latch count may cause issues");
 *        }
 *        return new CountDownLatch(count);
 *    }
 * 
 * 5. 正确处理异常:
 *    CountDownLatch latch = new CountDownLatch(5);
 *    
 *    for (int i = 0; i < 5; i++) {
 *        final int taskId = i;
 *        new Thread(() -> {
 *            try {
 *                performTask(taskId);
 *            } catch (Exception e) {
 *                System.err.println("Task " + taskId + " failed: " + e.getMessage());
 *                // 记录日志
 *            } finally {
 *                latch.countDown(); // 无论成功失败都要调用
 *            }
 *        }).start();
 *    }
 *    
 *    try {
 *        latch.await();
 *        System.out.println("All tasks finished (some may have failed)");
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt();
 *    }
 * 
 * 6. 使用超时机制:
 *    CountDownLatch latch = new CountDownLatch(1);
 *    
 *    // 不要无限期等待
 *    try {
 *        if (!latch.await(30, TimeUnit.SECONDS)) {
 *            System.out.println("Operation timed out after 30 seconds");
 *            // 处理超时情况
 *            handleTimeout();
 *        }
 *    } catch (InterruptedException e) {
 *        Thread.currentThread().interrupt();
 *    }
 * 
 * 7. 监控和调试:
 *    CountDownLatch latch = new CountDownLatch(10);
 *    
 *    // 定期检查计数器状态
 *    public void monitorProgress() {
 *        long currentCount = latch.getCount();
 *        System.out.println("Remaining tasks: " + currentCount);
 *        if (currentCount == 0) {
 *            System.out.println("All tasks completed");
 *        }
 *    }
 *    
 *    // 记录任务完成情况
 *    public void trackTaskCompletion(int taskId) {
 *        System.out.println("Task " + taskId + " completed, " + 
 *                          latch.getCount() + " tasks remaining");
 *        latch.countDown();
 *    }
 * 
 * 8. 避免重复调用countDown:
 *    CountDownLatch latch = new CountDownLatch(1);
 *    
 *    // 错误的做法:可能重复调用
 *    // if (someCondition) {
 *    //     latch.countDown();
 *    // }
 *    // latch.countDown(); // 可能重复调用
 *    
 *    // 正确的做法:确保只调用一次
 *    private final AtomicBoolean countedDown = new AtomicBoolean(false);
 *    
 *    public void safeCountDown() {
 *        if (countedDown.compareAndSet(false, true)) {
 *            latch.countDown();
 *        }
 *    }
 * 
 * 9. 合理使用多个门闩:
 *    // 启动门闩和完成门闩
 *    CountDownLatch startLatch = new CountDownLatch(1);
 *    CountDownLatch finishLatch = new CountDownLatch(5);
 *    
 *    // 工作线程
 *    for (int i = 0; i < 5; i++) {
 *        final int workerId = i;
 *        new Thread(() -> {
 *            try {
 *                startLatch.await(); // 等待启动信号
 *                System.out.println("Worker " + workerId + " started");
 *                performWork();
 *            } catch (InterruptedException e) {
 *                Thread.currentThread().interrupt();
 *            } finally {
 *                finishLatch.countDown(); // 完成后减少计数器
 *            }
 *        }).start();
 *    }
 *    
 *    // 控制线程
 *    new Thread(() -> {
 *        try {
 *            Thread.sleep(1000); // 准备时间
 *            System.out.println("Starting all workers...");
 *            startLatch.countDown(); // 发送启动信号
 *            
 *            System.out.println("Waiting for all workers to finish...");
 *            finishLatch.await(); // 等待所有工作完成
 *            System.out.println("All workers finished");
 *        } catch (InterruptedException e) {
 *            Thread.currentThread().interrupt();
 *        }
 *    }).start();
 * 
 * 10. 性能调优:
 *    // 在高并发场景下监控性能
 *    CountDownLatch latch = new CountDownLatch(1000);
 *    
 *    // 监控等待时间
 *    public void monitorAwaitTime() {
 *        long startTime = System.nanoTime();
 *        try {
 *            latch.await();
 *            long endTime = System.nanoTime();
 *            long duration = endTime - startTime;
 *            System.out.println("Wait time: " + duration + " nanoseconds");
 *        } catch (InterruptedException e) {
 *            Thread.currentThread().interrupt();
 *        }
 *    }
 *    
 *    // 批量操作优化
 *    public void batchCountDown(CountDownLatch latch, int count) {
 *        for (int i = 0; i < count; i++) {
 *            latch.countDown();
 *        }
 *    }
 */

5. 与其他同步机制的比较

/**
 * CountDownLatch vs CyclicBarrier vs Semaphore vs Phaser:
 * 
 * CountDownLatch:
 * - 一次性使用,计数器只能减少
 * - 支持一个或多个线程等待
 * - 支持多个线程减少计数器
 * - 不支持重置
 * - 适用于简单的等待/通知场景
 * 
 * CyclicBarrier:
 * - 可重复使用,支持重置
 * - 所有线程相互等待
 * - 到达屏障点后一起继续
 * - 支持回调函数
 * - 适用于分阶段并行计算
 * 
 * Semaphore:
 * - 控制资源访问数量
 * - 支持许可证的获取和释放
 * - 可以动态调整许可数量
 * - 支持公平性和非公平性
 * - 适用于资源池管理
 * 
 * Phaser:
 * - JDK 7新增,功能最强大
 * - 支持动态注册和注销参与者
 * - 支持分层组织
 * - 可重复使用
 * - 适用于复杂的同步场景
 * 
 * 性能对比:
 * - 简单等待:CountDownLatch > CyclicBarrier > Semaphore > Phaser
 * - 复杂同步:Phaser > CyclicBarrier > Semaphore > CountDownLatch
 * - 内存使用:CountDownLatch < CyclicBarrier < Semaphore < Phaser
 * - 功能丰富度:Phaser > CyclicBarrier > Semaphore > CountDownLatch
 * 
 * 选择建议:
 * - 简单等待多个事件完成:CountDownLatch
 * - 分阶段并行计算:CyclicBarrier
 * - 资源访问控制:Semaphore
 * - 复杂同步需求:Phaser
 * - 需要重置功能:CyclicBarrier或Phaser
 * - 高性能简单场景:CountDownLatch
 * 
 * 使用场景:
 * - CountDownLatch:主线程等待子线程完成、启动门闩、关闭门闩
 * - CyclicBarrier:并行计算、分阶段任务协调
 * - Semaphore:资源池、流量控制、连接池
 * - Phaser:复杂的工作流、动态参与者管理
 */

6. 总结

CountDownLatch 的核心特性:

  1. 一次性同步

    • 计数器只能减少,不能增加
    • 一旦归零不能重置
    • 保证语义的清晰性
    • 适用于一次性的同步需求
  2. 共享锁语义

    • 基于AQS的共享模式实现
    • 多个线程可以同时通过门闩
    • 提高并发性能
    • 支持共享锁的所有特性
  3. 灵活的等待机制

    • 支持无限期等待
    • 支持可中断等待
    • 支持超时等待
    • 提供多种等待选项
    • 满足不同的使用需求
  4. 高效的唤醒机制

    • 计数器归零时一次性唤醒所有等待线程
    • 避免逐个唤醒的开销
    • 提高唤醒效率
    • 减少系统调用次数
  5. 线程安全

    • 所有操作都是线程安全的
    • 支持高并发环境
    • 无死锁风险
    • 基于AQS的成熟实现
  6. 丰富的API

    • 提供详细的计数器查询
    • 支持监控和诊断
    • 便于调试和性能调优
    • 符合Java标准规范

适用场景:

  • 主线程等待多个子线程完成
  • 实现启动门闩
  • 实现关闭门闩
  • 协调多个线程的执行
  • 实现简单的屏障机制
  • 需要一次性同步的场景

注意事项:

  • 必须确保countDown被正确调用
  • 避免计数器永远不会归零的情况
  • 合理使用超时机制避免无限等待
  • 正确处理中断异常
  • 监控等待线程数量
  • 避免重复调用countDown

性能优化建议:

  1. 根据实际需求设置合适的计数器值
  2. 使用超时机制避免无限等待
  3. 正确处理中断异常
  4. 在finally块中调用countDown
  5. 监控计数器状态
  6. 避免不必要的等待
  7. 合理使用多个门闩
  8. 定期分析和调优性能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值