奇淫巧技,CompletableFuture 异步多线程是真的优雅

一个示例回顾Future
通过CompletableFuture实现上面示例
CompletableFuture创建方式
异步回调方法
异常回调
多任务组合回调
CompletableFuture使用有哪些注意点

在这里插入图片描述

一个示例回顾Future

一些业务场景我们需要使用多线程异步执行任务,加快任务执行速度。

JDK5新增了Future接口,用于描述一个异步计算的结果。

虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,我们必须使用Future.get()的方式阻塞调用线程,或者使用轮询方式判断 Future.isDone 任务是否结束,再获取结果。

这两种处理方式都不是很优雅,相关代码如下:

@Test  
public void testFuture() throws ExecutionException, InterruptedException {
   
     
    ExecutorService executorService = Executors.newFixedThreadPool(5);  
    Future<String> future = executorService.submit(() -> {
   
     
        Thread.sleep(2000);  
        return "hello";  
    });  
    System.out.println(future.get());  
    System.out.println("end");  
}  

与此同时,Future无法解决多个异步任务需要相互依赖的场景,简单点说就是,主线程需要等待子线程任务执行完毕之后在进行执行,这个时候你可能想到了CountDownLatch,没错确实可以解决,代码如下。

这里定义两个Future,第一个通过用户id获取用户信息,第二个通过商品id获取商品信息。

@Test  
 public void testCountDownLatch() throws InterruptedException, ExecutionException {
   
     
     ExecutorService executorService = Executors.newFixedThreadPool(5);  
     CountDownLatch downLatch = new CountDownLatch(2);  
     long startTime = System.currentTimeMillis();  
     Future<String> userFuture = executorService.submit(() -> {
   
     
         //模拟查询商品耗时500毫秒  
         Thread.sleep(500);  
         downLatch.countDown();  
         return "用户A";  
     });  

     Future<String> goodsFuture = executorService.submit(() -> {
   
     
         //模拟查询商品耗时500毫秒  
         Thread.sleep(400);  
         downLatch.countDown();  
         return "商品A";  
     });  

     downLatch.await();  
     //模拟主程序耗时时间  
     Thread.sleep(600);  
     System.out.println("获取用户信息:" + userFuture.get());  
     System.out.println("获取商品信息:" + goodsFuture.get());  
     System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");  

 }  

「运行结果」
获取用户信息:用户A
获取商品信息:商品A
总共用时1110ms
从运行结果可以看出结果都已经获取,而且如果我们不用异步操作,执行时间应该是:500+400+600 = 1500,用异步操作后实际只用1110。

但是Java8以后我不在认为这是一种优雅的解决方式,接下来来了解下CompletableFuture的使用。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/

通过CompletableFuture实现上面示例

@Test  
public void testCompletableInfo() throws InterruptedException, ExecutionException {
   
     
    long startTime = System.currentTimeMillis();  

      //调用用户服务获取用户基本信息  
      CompletableFuture<String> userFuture = CompletableFuture.supplyAsync(() ->  
              //模拟查询商品耗时500毫秒  
      {
   
     
          try {
   
     
              Thread.sleep(500);  
          } catch (InterruptedException e) {
   
     
              e.printStackTrace();  
          }  
          return "用户A";  
      });  

      //调用商品服务获取商品基本信息  
      CompletableFuture<String> goodsFuture = CompletableFuture.supplyAsync(() ->  
              //模拟查询商品耗时500毫秒  
      {
   
     
          try {
   
     
              Thread.sleep(400);  
          } catch (InterruptedException e) {
   
     
              e.printStackTrace();  
          }  
          return "商品A";  
      });  

      System.out.println("获取用户信息:" + userFuture.get());  
      System.out.println("获取商品信息:" + goodsFuture.get());  

      //模拟主程序耗时时间  
      Thread.sleep(600);  
      System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");  
}  

获取用户信息:用户A
获取商品信息:商品A
总共用时1112ms

通过CompletableFuture可以很轻松的实现CountDownLatch的功能,你以为这就结束了,远远不止,CompletableFuture比这要强多了。

比如可以实现 :任务1执行完了再执行任务2,甚至任务1执行的结果,作为任务2的入参数等等强大功能,下面就来学学CompletableFuture的API。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/yudao-cloud
视频教程:https://doc.iocoder.cn/video/

CompletableFuture创建方式

1、常用的4种创建方式
CompletableFuture源码中有四个静态方法用来执行异步任务

public static <U> CompletableFuture<U> supplyAsync(Supplier<U></
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Next2you

你真帅!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值