当前位置: 首页 > news >正文

CountDownLatch与CyclicBarrier的区别

在Android开发中,CountDownLatchCyclicBarrier都是用于线程同步的工具类,但设计目的和使用场景有本质区别。以下从​​核心差异​​和​​Android典型场景​​两方面深入解析:


⚙️ 一、核心区别对比

​特性​​CountDownLatch​​CyclicBarrier​
​设计目的​单向等待:主线程等待子任务完成(1对多)多向等待:线程组相互等待到达屏障点(多对多)
​计数器行为​一次性(归零后失效)可循环使用(自动/手动重置)
​触发机制​外部线程调用countDown()减计数线程主动调用await(),由最后一个到达的线程触发唤醒
​异常处理​线程中断仅影响自身某线程中断会导致所有等待线程抛出BrokenBarrierException
​回调支持​❌ 不支持✅ 支持Runnable barrierAction(屏障点触发后执行)

​一句话总结​​:

  • ​CountDownLatch​​:主等子(如司机等乘客到齐发车)
  • ​CyclicBarrier​​:子等子(如运动员等所有人到起跑线开跑)

📱 二、Android开发中的经典应用场景

​1. CountDownLatch:主线程等待异步任务完成​
  • ​场景1:初始化资源聚合​
    等待多个网络请求/数据库加载完成后更新UI:

    CountDownLatch latch = new CountDownLatch(3); // 3个子任务// 子任务完成时调用 latch.countDown()
    loadNetworkData(() -> latch.countDown());
    loadDatabase(() -> latch.countDown());
    loadLocalFiles(() -> latch.countDown());latch.await(); // 主线程阻塞等待
    updateUI();    // 所有资源加载完成后刷新UI
  • ​场景2:Activity等待多线程预处理​
    如启动页等待广告加载、用户数据预取完成后跳转主页:

    // 在SplashActivity中
    CountDownLatch initLatch = new CountDownLatch(2);
    fetchAdConfig(() -> initLatch.countDown());
    preloadUserData(() -> initLatch.countDown());if (initLatch.await(3, TimeUnit.SECONDS)) { // 带超时防止死等startActivity(new Intent(this, MainActivity.class));
    } else {showError("初始化超时");
    }
​2. CyclicBarrier:分阶段协同处理数据​
  • ​场景1:多线程分阶段计算​
    如游戏帧渲染:多个线程分别处理物理、音效、画面,每帧需同步:

    CyclicBarrier barrier = new CyclicBarrier(3, () -> {Log.d("RENDER", "一帧渲染完成"); // 每帧完成后执行
    });executor.execute(() -> {calculatePhysics();barrier.await(); // 等待其他线程renderGraphics();
    });
    // 其他线程类似
  • ​场景2:动态重置的同步点​
    如批量下载任务分批次处理(每批N个文件下载完成后开始压缩):

    CyclicBarrier batchBarrier = new CyclicBarrier(5, () -> {compressBatchFiles(); // 每5个文件下载完成后压缩
    });for (File file : files) {downloadFile(file, () -> batchBarrier.await());
    }

⚠️ 三、使用注意事项

​问题​​CountDownLatch​​CyclicBarrier​
​死锁风险​子线程未调用countDown()导致主线程永久阻塞 → ​​需设超时​await(timeout, unit)线程被中断导致屏障损坏 → ​​需捕获BrokenBarrierException并重置reset()
​性能开销​基于AQS实现,轻量级依赖ReentrantLock,较重(适合低频同步)
​动态调整参与者​❌ 初始化后不可变✅ 通过reset()重置(需处理中断)

💎 四、总结:Android中的选型建议

​场景特征​​推荐工具​​示例​
主线程等待多个异步任务结果CountDownLatch启动页聚合初始化任务
多线程分阶段执行+重复同步CyclicBarrier游戏帧同步、批量下载分批次处理
需回调通知阶段完成CyclicBarrier所有线程到达屏障后触发日志/埋点

​决策树​​:

  1. 是否需​​主线程等待​​? → 选CountDownLatch
  2. 是否需​​线程组互相等待+多阶段重用​​? → 选CyclicBarrier
  3. 是否需​​阶段完成回调​​? → 选CyclicBarrier(搭配barrierAction

合理选择同步工具,可避免Handler手工同步的复杂性,提升多线程代码可维护性。在资源初始化、分批次任务等高频场景中,二者能显著简化并发设计。

http://www.dtcms.com/a/250963.html

相关文章:

  • AOP +ThreadLocal实现对接口监控
  • 共享内存实现进程通信
  • C++ STL常用二分查找算法
  • 第二十六周:序列化和反序列化
  • Jenkins 全面深入学习目录
  • MFE微前端:如何捕捉远程应用的remote.js加载失败的错误?
  • 001微信小程序入门
  • sql中like and not like的优化
  • Web后端基础:数据库
  • 【1】Redis 缓存穿透原理和解决方案
  • 操作系统核心名词解释--期末简答题快速复习
  • 【深度解析】Java高级并发模式与实践:从ThreadLocal到无锁编程,全面避坑指南!
  • Python 训练营打卡 Day 46-通道注意力
  • 电影院管理系统的设计与实现
  • VINS-Fusion 简介、安装、编译、数据集/相机实测
  • Linux系统编程 | IPC对象---共享内存
  • 算法的几大模块
  • HTML 从入门到起飞 · 系列合集:一站式学习不掉线
  • htmlcss考核
  • 6.11小测(html、css)
  • [深度学习]目标检测基础
  • RADIUS服务器的核心应用场景与ASP认证服务器的快速对接指南
  • MIT线性代数第二讲笔记
  • docker(学习笔记第一课) 使用nginx +https + wordpress
  • 视觉通才模型:最新综述 [ 2025 IJCV ]
  • AI for 数据分析:技术演进与应用实践
  • Flink CDC MySQL 表字段定义为 decimal 输出乱码问题优雅解决方式
  • logback常用配置
  • aws(学习笔记第四十四课) opensearch
  • ShardingSphere 全面学习路径