在分布式项目中,通过分布式架构实现相关功能调用,这是必然存在的。我在项目中,比如商品详情信息页面的展示,分享图的合成等场景,都会涉及到好几个分模块功能获取信息。CountdownLatch则可以很好的实现类似场景的功能实现。
CountdownLatch基本介绍
能够使一个线程等待其他线程完成各自的工作之后再执行。
详情:并发编程–CountdownLatch && CyclicBarrier
场景介绍
结合actor和course信息合成一张分享图,只介绍流程,核心代码模拟。
代码实现
public class CountDownLatchService {
protected Actor actor;
protected Course course;
protected CountDownLatchService(Actor actor, Course course) {
this.actor = actor;
this.course = course;
}
private static final int threadSize = 5;
private boolean isRunning = false;
private static final CountDownLatch latch = new CountDownLatch(2);
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
threadSize + 1,
threadSize + 1,
10,
TimeUnit.SECONDS
, new SynchronousQueue<>());
public int init() {
if (isRunning == true) {
System.out.println("线程正在运行...");
return -1;
}
isRunning = true;
executor.execute(() -> {
System.out.println("获取actor相关信息");
course.setName("霍霍的courseName");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
System.out.println("1:"+latch.getCount());
});
executor.execute(() -> {
System.out.println("获取course的name");
actor.setName("霍霍的actorName");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
System.out.println("2:"+latch.getCount());
});
executor.execute(() -> {
System.out.println("获取course的type");
//仅仅测试模拟,真实项目可能就是分布式相关任务调用
course.setType(1L);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
System.out.println("3:"+latch.getCount());
});
executor.execute(() -> {
System.out.println("等待所有信息返回=");
try {
System.out.println("value:"+latch.getCount());
latch.await();
//设置isRunning=false
isRunning = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("course info= " + course.getName());
System.out.println("actor info= " + actor.getName());
//执行额外的拼接合成逻辑
System.out.println("拼接图片完成");
});
executor.shutdown();
System.out.println("信息返回结束");
return 0;
}
public static void main(String[] args) {
Actor actor = new Actor();
Course course = new Course();
CountDownLatchService countDownLatchService = new CountDownLatchService(actor, course);
countDownLatchService.init();
}
}
需要注意的点
CountDownLatch初始值需谨慎考虑,比如如上demo,我需要三个获取信息的线程去执行,每次执行latch.countDown(),count就会减1.当count为0的时候,就会执行await。
想表达什么意思呢?
比如你初始值是2,执行了三个latch.countDown();
比如你初始值是4,执行了三个latch.countDown();
两个结果肯定是不同的,你去看源码就会发现,所有调用await方法的线程都会阻塞在 AQS 的阻塞队列中,通过判定count是否为0来决定是否唤起。