CountDownLatch 和 CyclicBarrier 的基本使用
2019-01-29 21:40 hduhans 阅读(342) 评论(0) 编辑 收藏 举报CountDownLatch 和 CyclicBarrier 是并发编程中常用的辅助类,两者使用上有点类似,但又有不同。
CountDownLatch 可是实现类似计数器的功能,比如一个线程 A 需要等待其余多个任务执行完毕后才能执行,此时可以使用这个工具类。
构造器:
public CountDownLatch(int count) { }
主要方法:
public void await() throws InterruptedException { }; // 调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; // 和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行 public void countDown() { }; // 将count值减1
示例方法:

public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(2); new Thread() { @Override public void run() { try { System.out.println("子线程" + Thread.currentThread().getName() + "正在执行"); Thread.sleep(3000); System.out.println("子线程" + Thread.currentThread().getName() + "执行完毕"); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); new Thread() { @Override public void run() { try { System.out.println("子线程" + Thread.currentThread().getName() + "正在执行"); Thread.sleep(3000); System.out.println("子线程" + Thread.currentThread().getName() + "执行完毕"); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); try { System.out.println("等待2个子线程执行完毕..."); latch.await(); System.out.println("2个子线程已经执行完毕"); System.out.println("继续执行主线程"); } catch (InterruptedException e) { e.printStackTrace(); } }
执行结果:
子线程Thread-0正在执行 等待2个子线程执行完毕... 子线程Thread-1正在执行 子线程Thread-1执行完毕 子线程Thread-0执行完毕 2个子线程已经执行完毕 继续执行主线程
CyclicBarrier 可以称为回环栅,可以实现所有线程同时执行某动作的效果。比如跑步运动员在比赛前需要进行准备工作,等所有运动员都准备完毕后,同时开始比赛。
构造器:
public CyclicBarrier(int parties) { } // 设置线程数量 public CyclicBarrier(int parties, Runnable barrierAction) { } // 设置线程数量,并设置所有线程 await 执行完毕后的方法
主要方法:
public int await() throws InterruptedException, BrokenBarrierException { }; // 挂起线程,直至所有线程达到 barrier 状态再执行 public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { }; // 同上,挂起线程,等待一定的时间
示例方法:

public class CyclicBarrierTest { public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println("所有运动员准备完毕,倒计时3秒后比赛开始...我是裁判:" + Thread.currentThread().getName() + ",当前时间:" + System.currentTimeMillis()); } }); new Competition(barrier, "张三").start(); new Competition(barrier, "李四").start(); new Competition(barrier, "王五").start(); } /** * 跑步比赛内容,所有人准备工作完成后,起跑 */ static class Competition extends Thread { private CyclicBarrier cyclicBarrier; private String name; public Competition(CyclicBarrier cyclicBarrier, String name) { this.cyclicBarrier = cyclicBarrier; this.name = name; } @Override public void run() { int time = new Random().nextInt(10); System.out.println(name + "开始准备工作,预计耗时:" + time + "秒"); try { // 准备中 Thread.sleep(time * 1000); System.out.println(name + "准备完成,等待其他运动员完成"); cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } // 起跑倒计时 try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } System.out.println(name + "已经起跑...当前时间:" + System.currentTimeMillis()); } } }
执行结果:
张三开始准备工作,预计耗时:5秒 王五开始准备工作,预计耗时:2秒 李四开始准备工作,预计耗时:6秒 王五准备完成,等待其他运动员完成 张三准备完成,等待其他运动员完成 李四准备完成,等待其他运动员完成 所有运动员准备完毕,倒计时3秒后比赛开始...我是裁判:Thread-1,当前时间:1548768695636 张三已经起跑...当前时间:1548768698637 王五已经起跑...当前时间:1548768698637 李四已经起跑...当前时间:1548768698637
执行分析:
三个运动员每个人是一个线程,执行比赛这一个动作。准备工作和起跑是比赛动作的两个部分,其中准备工作耗时不同,起跑动作又需要所有运动员都准备完毕才可以进行。线程启动后,每个运动员执行自身的准备工作,然后阻塞等待其余所有线程执行完准备工作(执行完 await 前序动作),再同时执行各自线程的剩余工作(起跑)。
图1 CyclicBarrier 执行过程分析
1、CountDownLatch 不可重置,无法重用;CyclicBarrier 可以重置,允许重复使用。
2、CountDownLatch 等待对象是一个线程等待多个线程执行完毕后,再自身执行,而 CyclicBarrier 是多个线程之间相互等待,等所有线程执行到统一状态时,再同时执行后续动作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架