Java使用CountDownLatch实现网络同步请求的示例代码

作者:抓手 时间:2022-04-23 18:40:52 

CountDownLatch 是一个同步工具类,用来协调多个线程之间的同步,它能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。

这里是使用CountDownLatch和多线程完成商品信息异步组装:

import java.time.LocalDateTime;
import java.util.StringJoiner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* @author 向振华
* @date 2023/01/04 14:01
*/
public class Test {

public static void main(String[] args) {

// 创建线程池
       ExecutorService executorService = Executors.newFixedThreadPool(10);

CountDownLatch countDownLatch = new CountDownLatch(3);

System.out.println("开始 " + LocalDateTime.now());

StringJoiner sj = new StringJoiner("、");

// 线程1
       executorService.execute(() -> {
           try {
               String do1 = do1();
               sj.add(do1);
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               countDownLatch.countDown();
           }
       });

// 线程2
       executorService.execute(() -> {
           try {
               String do2 = do2();
               sj.add(do2);
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               countDownLatch.countDown();
           }
       });

// 线程3
       executorService.execute(() -> {
           try {
               String do3 = do3();
               sj.add(do3);
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               countDownLatch.countDown();
           }
       });

try {
           countDownLatch.await();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

System.out.println(sj.toString());
       System.out.println("完成 " + LocalDateTime.now());
   }

private static String do1() {
       try {
           Thread.sleep(1000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("1查询商品规格信息");
       return "商品规格";
   }

private static String do2() {
       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("2查询商品价格信息");
       return "商品价格";
   }

private static String do3() {
       try {
           Thread.sleep(3000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("3查询商品图片信息");
       return "商品图片";
   }
}

输出结果:

开始 2023-01-04T14:16:40.441
1查询商品规格信息
3查询商品图片信息
2查询商品价格信息
商品规格、商品图片、商品价格
完成 2023-01-04T14:16:45.468

知识补充

1.背景

  • countDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。

  • 存在于java.util.cucurrent包下

2.概念

countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。

是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

3.源码

countDownLatch类中只提供了一个构造器:

//参数count为计数值
public CountDownLatch(int count) {  };  

类中有三个方法是最重要的:

//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException { };  
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  
//将count值减1
public void countDown() { };  

4.示例

普通示例

public class CountDownLatchTest {

public static void main(String[] args) {
       final CountDownLatch latch = new CountDownLatch(2);
       System.out.println("主线程开始执行…… ……");
       //第一个子线程执行
       ExecutorService es1 = Executors.newSingleThreadExecutor();
       es1.execute(new Runnable() {
           @Override
           public void run() {
               try {
                   Thread.sleep(3000);
                   System.out.println("子线程:"+Thread.currentThread().getName()+"执行");
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               latch.countDown();
           }
       });
       es1.shutdown();

//第二个子线程执行
       ExecutorService es2 = Executors.newSingleThreadExecutor();
       es2.execute(new Runnable() {
           @Override
           public void run() {
               try {
                   Thread.sleep(3000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.println("子线程:"+Thread.currentThread().getName()+"执行");
               latch.countDown();
           }
       });
       es2.shutdown();
       System.out.println("等待两个线程执行完毕…… ……");
       try {
           latch.await();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("两个子线程都执行完毕,继续执行主线程");
   }
}

结果集:

主线程开始执行…… ……
等待两个线程执行完毕…… ……
子线程:pool-1-thread-1执行
子线程:pool-2-thread-1执行
两个子线程都执行完毕,继续执行主线程

来源:https://blog.csdn.net/Anenan/article/details/128547521

标签:Java,CountDownLatch,网络,同步,请求
0
投稿

猜你喜欢

  • java 中Map详解及实例代码

    2023-06-06 01:27:37
  • C#实现窗口之间的传值

    2022-05-26 08:28:14
  • C#微信公众号开发之接收事件推送与消息排重的方法

    2022-01-31 08:44:46
  • Android编程之文件读写操作与技巧总结【经典收藏】

    2023-10-16 02:20:52
  • java interface的两个经典用法

    2021-08-17 06:20:56
  • 使用@Validated 和 BindingResult 遇到的坑及解决

    2022-12-18 20:36:28
  • Android中的SQL查询语句LIKE绑定参数问题解决办法(sqlite数据库)

    2023-09-12 14:04:06
  • Java如何利用状态模式(state pattern)替代if else

    2021-08-15 09:31:08
  • MyBatis一对多嵌套查询的完整实例

    2023-07-12 02:49:56
  • winform导出dataviewgrid数据为excel的方法

    2023-09-25 15:01:38
  • Android服务Service教程

    2022-02-19 13:05:40
  • 关于springboot中对sqlSessionFactoryBean的自定义

    2022-12-09 06:05:09
  • C#实现插入排序

    2023-07-02 13:16:58
  • Springboot Session共享实现原理及代码实例

    2022-12-16 03:29:52
  • Java Swing实现让窗体居中显示的方法示例

    2023-11-06 02:59:07
  • Android Universal ImageLoader 缓存图片

    2023-03-04 05:16:54
  • Gradle的基本使用

    2023-05-29 00:08:42
  • spring data JPA 中的多属性排序方式

    2023-01-14 19:26:41
  • Android平台预置GMS包后关机闹钟失效问题及解决方法

    2022-12-31 05:52:33
  • idea打包java程序(包含依赖的所有jar包)

    2023-02-13 00:10:26
  • asp之家 软件编程 m.aspxhome.com