并发编程--CountdownLatch结合线程池实现

本文介绍了在分布式项目中如何利用CountDownLatch进行线程间的协调,确保所有必要的信息获取完成后再执行后续操作。例如,在合成分享图的场景中,多个模块并行获取actor和course信息,CountDownLatch用于等待所有线程执行完毕。代码示例展示了如何初始化CountDownLatch,创建线程池执行任务,并在所有任务完成后执行合成逻辑。
摘要由CSDN通过智能技术生成

在分布式项目中,通过分布式架构实现相关功能调用,这是必然存在的。我在项目中,比如商品详情信息页面的展示,分享图的合成等场景,都会涉及到好几个分模块功能获取信息。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来决定是否唤起。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值