资讯详情

JUC并发工具三兄弟:CountDownLatch、CyclicBarrier、Semaphore一次讲透

📅 2026/10/10 12:09:35 | 华诺云谱 👁 阅读
JUC并发工具三兄弟:CountDownLatch、CyclicBarrier、Semaphore一次讲透
大家好我是陪你系统复习的老周。并发模块前三块synchronized、volatile、线程池讲完了今天讲第四块——JUC并发工具三兄弟。这三个工具是面试高频考点也是实际项目中天天用的。很多人背了概念但分不清区别今天咱们用生活化比喻可运行代码一次讲透。一、为什么需要这三兄弟synchronized 解决了同一时刻只能一个人进的问题volatile 解决了改了别人能看到的问题。但实际项目中还有大量线程协作场景主线程要等所有子线程干完活再汇总怎么办多个线程要同时到达某个点再一起起跑模拟并发怎么办最多只能3个线程同时调第三方接口怕被封怎么办JUC 包给了三个工具分别对应这三个场景。一句话记住CountDownLatch 一个等多个CyclicBarrier 多个互等Semaphore 限制并发数。二、CountDownLatch发令枪想象运动会跑步比赛裁判主线程举着发令枪等所有运动员子线程都就位后倒计时3、2、1枪响所有人同时起跑。CountDownLatch 内部有个计数器构造时设初始值。每个子线程干完活调用countDown()计数器减1。主线程调用await()阻塞等计数器变成0就继续。关键点计数器只能减不能加用完就废了是一次性的。基本用法CountDownLatchlatchnewCountDownLatch(3);latch.countDown();// 子线程干完调用计数器减1latch.await();// 主线程阻塞等计数器到0完整可运行代码importjava.util.concurrent.CountDownLatch;publicclassCountDownLatchDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{CountDownLatchlatchnewCountDownLatch(3);for(inti1;i3;i){finalintidi;newThread(()-{System.out.println(线程id开始干活);try{Thread.sleep(500);}catch(InterruptedExceptione){}System.out.println(线程id干完了countDown);latch.countDown();}).start();}System.out.println(主线程等待所有子线程完成...);latch.await();System.out.println(所有子线程完成主线程继续);}}运行输出主线程等待所有子线程完成... 线程2开始干活 线程3开始干活 线程1开始干活 线程2干完了countDown 线程3干完了countDown 线程1干完了countDown 所有子线程完成主线程继续典型场景并行加载多个数据源全部加载完再汇总压测时等所有线程就绪再同时开始。大坑提醒countDown() 一定要放 finally 里如果子线程抛异常没走到 countDown计数器永远到不了0await 永久阻塞。三、CyclicBarrier旅游团集合想象旅游团导游规定上午9点在酒店大堂集合所有人到齐了一起出发。到了景点A又规定12点集合人到齐再去景点B。这个集合点可以反复用。CyclicBarrier 就是这个循环集合点。构造时指定需要多少个线程到齐每个线程调用await()表示我到了等其他人。所有人到齐后一起继续执行。下一轮还能再用。关键点和 CountDownLatch 最大的区别是——CyclicBarrier 可以循环重置使用。基本用法CyclicBarrierbarriernewCyclicBarrier(3,()-System.out.println(所有人到齐一起出发));barrier.await();// 每个线程调用到齐才放行构造时第二个参数是 Runnable所有人到齐时自动执行类似集合完毕导游讲话。完整可运行代码importjava.util.concurrent.CyclicBarrier;publicclassCyclicBarrierDemo{publicstaticvoidmain(String[]args){CyclicBarrierbarriernewCyclicBarrier(3,()-System.out.println( 所有人到齐一起出发 ));for(inti1;i3;i){finalintidi;newThread(()-{try{System.out.println(线程id到达集合点等待其他人);barrier.await();System.out.println(线程id继续执行第二阶段);Thread.sleep(300);barrier.await();System.out.println(线程id完成第三阶段);}catch(Exceptione){}}).start();}}}运行输出线程3到达集合点等待其他人 线程2到达集合点等待其他人 线程1到达集合点等待其他人 所有人到齐一起出发 线程3继续执行第二阶段 线程2继续执行第二阶段 线程1继续执行第二阶段 所有人到齐一起出发 线程1完成第三阶段 线程3完成第三阶段 线程2完成第三阶段注意看屏障用了两轮这就是Cyclic循环的含义。典型场景多线程迭代计算每轮算完汇总再进下一轮模拟并发请求所有线程同时起跑压测。四、Semaphore停车场管理员想象停车场只有3个车位来了5辆车。管理员Semaphore发停车券前3辆拿到券进去停后2辆在门口等。有车出来交还券等待的车补上。Semaphore 维护一组许可permitsacquire()获取许可没有就等release()归还许可。new Semaphore(3) 就表示最多3个线程同时访问资源。关键点Semaphore 本质是一个允许多个线程同时进入的共享锁。基本用法SemaphoresemnewSemaphore(3);sem.acquire();// 获取许可没有就阻塞// 使用资源sem.release();// 归还许可完整可运行代码importjava.util.concurrent.Semaphore;publicclassSemaphoreDemo{publicstaticvoidmain(String[]args){SemaphoresemnewSemaphore(3);for(inti1;i5;i){finalintidi;newThread(()-{try{System.out.println(线程id请求许可可用sem.availablePermits());sem.acquire();System.out.println(线程id获得许可开始使用资源);Thread.sleep(500);System.out.println(线程id用完释放许可);sem.release();}catch(InterruptedExceptione){}}).start();}}}运行输出线程1请求许可可用3 线程2请求许可可用3 线程5请求许可可用3 线程3请求许可可用3 线程4请求许可可用3 线程2获得许可开始使用资源 线程5获得许可开始使用资源 线程1获得许可开始使用资源 线程5用完释放许可 线程3获得许可开始使用资源 线程2用完释放许可 线程4获得许可开始使用资源 线程1用完释放许可 线程3用完释放许可 线程4用完释放许可前3个线程2、5、1同时获得许可后2个3、4等释放后才补上。典型场景接口限流限制QPS、数据库连接池控制、第三方API调用频率限制。五、三兄弟对比表维度CountDownLatchCyclicBarrierSemaphore作用一个线程等N个N个线程互等限制并发数能否复用不能一次性能可循环能许可可归还核心方法countDown/awaitawaitacquire/release计数方向递减到0递增到N许可增减类比发令枪旅游团集合停车场一句话区分CountDownLatch 是裁判等运动员就位CyclicBarrier 是运动员互相等人到齐Semaphore 是停车场限车位。六、实战组合用法实际项目中三者经常组合CountDownLatch主线程等10个数据加载线程全部完成CyclicBarrier10个线程每加载完一批在屏障点汇总后再加载下一批Semaphore限制同时调第三方接口的线程不超过3防止被限流封禁各司其职组合使用威力大。七、高频面试题QCountDownLatch 和 CyclicBarrier 区别CountDownLatch 是一个线程等多个计数器递减一次性不可复用CyclicBarrier 是多个线程互相等计数器递增可循环重置。QSemaphore 和 synchronized 区别synchronized 只允许1个线程Semaphore 允许N个synchronized 必须同线程加锁解锁Semaphore 可以不同线程 acquire 和 release。QCyclicBarrier 一个线程超时了其他线程怎样超时线程抛 TimeoutException屏障标记为 broken其他等待线程抛 BrokenBarrierException需要 reset() 重置。口诀CountDownLatch 倒计时一个等多个一次性 CyclicBarrier 循环栏多个互等可复用 Semaphore 信号量限流控并发许可数 countDown 放 finally屏障 broken 要重置。JUC并发工具三兄弟就讲到这里。这三个是并发编程的基础协作工具掌握了它们后面的 CompletableFuture、线程池组合使用都会更顺手。下一期讲ThreadLocal并发模块的又一个高频考点敬请关注。如果这篇对你有帮助欢迎点赞、收藏、关注咱们每周一三五一个Java知识块系统复习不迷路。#Java面试 #JUC #CountDownLatch #CyclicBarrier #Semaphore #并发编程 #多线程 #后端开发
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑