CountDownLatch应用场景实践

    技术2022-07-15  80

    一.CountDownLatch介绍

            CountDownLatch是一个并发工具类, 作用是允许一个或多个线程等待其他线程完成操作。我们有时会称之为发令枪。有一个个形象的例子能说明其功能:公司召开一个全体股东会,需要所有股东到场了才能正式开始。会议室准备了一个花名册,记录了需要到会的总人数,每一个股东来到会议室就要签名确认,同时总人数减一,当需要到会的总人数为0时,会议就正式开始。所以,CountDownLatch就有充当计数器和发令枪的功能。

    二.结合ExecutorService实现拆分任务并发执行

           一般我们业务场景中经常会有执行一个大任务,如果我们串行执行,则效率较慢。我们应用分而治之的思想,将其拆分,启动多个线程来并行。但是如果目前不阻塞主线程,可能在子线程进行中的过程中,主线程已结束。这样也无法最终汇总结果了。此时引入CountDownLatch便能解决这个痛点。

    //利用countDownLatch结合ExecutorService在并发执行任务时,能够保证子线程任务结束后,主线程才继续往下走。 CountDownLatch countDownLatch = new CountDownLatch(3); ExecutorService executorService = Executors.newFixedThreadPool(3); Runnable runnable1 = () -> { System.out.println(111111); countDownLatch.countDown(); }; Runnable runnable2 = () -> { System.out.println(222222); countDownLatch.countDown(); }; Runnable runnable3 = () -> { System.out.println(333333); countDownLatch.countDown(); }; executorService.execute(runnable1); executorService.execute(runnable2); executorService.execute(runnable3); //阻塞当前主线程 countDownLatch.await(); System.out.println("主线程结束返回结果");

    任务拆分为几个线程来执行,则CountDownLatch就是多少。

    当子线程都执行完毕了,此时CountDownLatch为0,主线程不再阻塞,继续往下走。

    三.模拟高并发

    有时我们写测试用例时,想要模拟一些并发场景,这时可以引入CountDownLatch。

    private static final int MAX_THREAD = 10000; private CountDownLatch cdl = new CountDownLatch(MAX_THREAD); @Test public void countDownLatchTest() throws InterruptedException { //模拟并发 for (int i =0;i<MAX_THREAD;i++){ Thread thread = new Thread(() -> { cdl.countDown(); try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } //测试调用业务接口等 System.out.println(new Date()); }); thread.start(); } Thread.sleep(2000); }

    如上便是模拟10000的并发,主线程肯定要sleep下,不然直接就结束了,子线程的结果也会来不及打印出来。

    Processed: 0.010, SQL: 9