Springboot中@Async异步,实现异步结果合并统一返回_springboot异步返回结果-程序员宅基地

技术标签: java  多线程  SpringBoot  

本文章是为了实现在SpringBoot中使用@Async异步时,将所有异步返回的结果合并

举例:如果我们想拉取三个数据,每个数据拉取时间是2秒钟,想将结果统一返回给前端,以往我们都是这么做

    @Override
    public SysUser getUserA() throws InterruptedException {
        System.out.println("A线程:"+Thread.currentThread().getId());
        SysUser sysUser = new SysUser();
        sysUser.setUserName("A用户");
        Thread.sleep(2000L);
        System.out.println("A 拉取成功");
        return sysUser;
    }
    @Override
    public SysUser getUserB() throws InterruptedException {
        System.out.println("B线程:"+Thread.currentThread().getId());
        SysUser sysUser = new SysUser();
        sysUser.setUserName("B用户");
        Thread.sleep(2000L);
        System.out.println("B 拉取成功");
        return sysUser;
    }
    @Override
    public SysUser getUserC() throws InterruptedException {
        System.out.println("C线程:"+Thread.currentThread().getId());
        SysUser sysUser = new SysUser();
        sysUser.setUserName("C用户");
        Thread.sleep(2000L);
        System.out.println("C 拉取成功");
        return sysUser;
    }

执行拉取测试

    @Test
    public void testAsync() throws Exception{
        System.out.println(new Date());
        SysUser a = sysUserService.getUserA();
        SysUser b = sysUserService.getUserB();
        SysUser c = sysUserService.getUserC();
        List<SysUser> list = new ArrayList<>(Arrays.asList(a,b,c));
        list.forEach(user->{
            System.out.println(user.getUserName());
        });
        System.out.println(new Date());
    }

结果:共耗时6秒(一个结果2秒)

如果我们有个需求 ,这三个数据一起返回给前端不能超过5秒,这种情形我们就会使用到异步,

问题:但是如果使用异步,主线程不会等待异步线程返回,会直接执行之后代码返回前端(如下图),前端接收到的就是null

解决:如果我们想达到异步的结果统一返回,就需要使用到CompletableFuture

 注:使用@Async时,需要@EnableAsync开启异步,调用@Async的方法不能与@Async所在同一个类中

 执行测试:等待异步返回,并收集结果,使用.get获取返回值

 结果:可以看出每个方法都是异步并行,2秒就即可返回三个合并后的结果

 当前执行流程

为什么耗时是2秒:

CompletableFuture.allOf(a,b,c).join();
我们这里 allOf 传递了 三个 异步线程的返回值, 所以看到上图,也就出现了三个等待返回值的坑位 A B C。
可以把这个想象成一辆车,三个位, 必须人满才发车。

那么要等多久呢?
这三个人几乎是同时走向这辆车的,但是无论其他人走多快,因为得整整齐齐,所以耗时取决于这三个坑位,最慢上车的那个人。

 如果我把其中一个B线程改为10秒

结果:可以看出B线程拉取的最慢,并且总耗时为10秒

 

 注意:

其实,只要你使用到了  返回接收值CompletableFuture ,其实就已经开始触发,并不是一定要用allOf。 

例如:如果我们在使用CompletableFuture时,在异步中途使用到返回值,那么主线程会等待这个异步线程返回


 结果:可以看出主线程一直在等待B线程的返回结果,等待10秒后才继续直接线程C

结论:只要调用了get(),主线程就会等待异步线程结果的返回

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yangjiaaiLM/article/details/124316542

智能推荐

Django JSONField的自动转换(django自定义模型字段)-程序员宅基地

文章浏览阅读1.8k次。Django v3.1的主要更新之一便是完善了对JSON数据存储的支持,新增models.JSONField和forms.JSONField,可在所有受支持的数据库后端上使用。_django jsonfield

你写的API接口代码真是惨不忍睹,就不能对返回格式统一处理吗?_某个接口不需要统一返回处理-程序员宅基地

文章浏览阅读607次。随着互联网各岗位精细化分工的普及,出现了很多的系统架构设计,比如常见的前后端分离架构,后端提供接口给前端,前端根据接口的数据进行渲染,大家各执其职,效率也非常的高,但是随着接口的增加,如果不统一的规范就会额外的增加大量的沟通成本以及学习成本,对管理者而言是非常的不利。为此,我在这篇文章分享给大家一个Java生鲜电商平台中如何返回统一格式的API的整体架构设计。一般系统的大致整体架构图如下:..._某个接口不需要统一返回处理

一文掌握磁盘分区全知识:为何分区、分区种类及分区表的选择_分区有哪些类型,设置活动分区的目的是什么-程序员宅基地

文章浏览阅读953次,点赞19次,收藏19次。磁盘分区就像是我们整理衣柜或者设计户型图,通过合理的划分和管理,可以让我们更高效地使用计算机,同时也可以保护我们的数据安全。所以,理解和掌握磁盘分区的知识,对于我们来说是非常重要的。_分区有哪些类型,设置活动分区的目的是什么

STM32F4学习笔记12——RNG随机数发生器_ll_rng_isactiveflag_drdy-程序员宅基地

文章浏览阅读1w次,点赞3次,收藏8次。RNG主要特性 RNG 处理器是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个 32 位的 随机数。RNG的主要特性 ● 提供由模拟量发生器产生的 32 位随机数 ● 两个连续随机数的间隔为 40 个 PLL48CLK 时钟信号周期 ● 通过监视 RNG 熵来标识异常行为(产生稳定值,或产生稳定的值序列) ● 可被禁止以降低功耗RNG功能描述 随机数发生器采用模拟电路实_ll_rng_isactiveflag_drdy

【PostgreSQL】PostgreSQL函数-得到表的建表语句、得到整个schema的ddl语句_pg数据库获取建表ddl语句-程序员宅基地

文章浏览阅读1.6k次,点赞40次,收藏12次。【代码】【PostgreSQL】PostgreSQL函数-得到表的建表语句、得到整个schema的ddl语句_pg数据库获取建表ddl语句

MySQl基础入门 ⑮-程序员宅基地

文章浏览阅读949次,点赞12次,收藏27次。创建视图与使用

随便推点

TensorFlow中accuracy.eval函数,softmax回归_eval('softmax')-程序员宅基地

文章浏览阅读1.8k次。下面是用TensorFlow实现Logistic Regression,步骤都做了标注,不详细说了。#encoding:utf-8import tensorflow as tf# 装在MNIST数据from tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("..._eval('softmax')

练习wps计算机考试需要开通会员吗,不想开WPS会元,教你如何免费使用它会员功能...-程序员宅基地

文章浏览阅读4.5k次。原标题:不想开WPS会元,教你如何免费使用它会员功能关于PDF格式转换的问题,小仙女也给大家推送过不少软件和网站,有单独转换的,有即可以转换又可以编辑的,都非常好用。但是小仙女平时分享的无论是软件还是网站,基本都是电脑端产品,电脑编辑PDF文档确实方便,但是我们总不能时时刻刻把电脑带在身上。有时候出门在外,遇到需要处理的紧急文档该怎么办呢?这个时候你可能会想到用手机啊,手机上装个WPS就好了。WP..._计算机报考wps的话会不会有会员

C++开发实战(二):打开已有工程,并编译生成dll、exe等文件_此项目需要 mfc 库。从 visual studio 安装程序(单个组件选项卡)为正在使用的任何-程序员宅基地

文章浏览阅读1.4w次。一、打开已有工程遇到的问题1、如下几张图,提示很友好,但我都点击了确定,并进行了运行,提示:此项目需要 MFC 库。从 Visual Studio 安装程序(单个组件选项卡)为正在使用的任何。。。2、根据提示安装依赖库(1)搜索栏搜索应用Visual Studio Installer(2)双击打开,选择单个组件安装,选择MFC 库进行安装..._此项目需要 mfc 库。从 visual studio 安装程序(单个组件选项卡)为正在使用的任何

牛牛做数论 <每日一题分享>-程序员宅基地

文章浏览阅读834次。题目:做题思路:做这题我们首先要了解什么是欧拉函数欧拉函数:就是对于一个正整数n,小于n且和n互质的正整数(包括1)的个数,记作φ(n) 。欧拉函数的通式:φ(n)=n*(1-1/p1)(1-1/p2)(1-1/p3)*(1-1/p4)……(1-1/pn)其中p1, p2……pn为n的所有质因数,n是不为0的整数。φ(1)=1(唯一和1互质的数就是1本身)。那么题目所给的H(x)表达式为H(x)=(1-1/p1)(1-1/p2)(1-1/p3)*(1-1/p4)……(

vue-router query和params传参(接收参数)$router $route的区别-程序员宅基地

文章浏览阅读289次。今天做项目时踩到了vue-router传参的坑(query和params),所以决定总结一下二者的区别。直接总结干货!!!1.query方式传参和接收参数传参: this.$router.push({ path:'/xxx', query:{ id:id } ..._vue query传参与接收参数将参数绑定

Windows下实现生产者-消费者模型_在windows环境下,利用高级语言编程环境(限定为vs环境)调用createthread函数实现“-程序员宅基地

文章浏览阅读4.6k次,点赞9次,收藏47次。要求在 windows 环境下,利用高级语言编程环境(限定为 VS 环境或 VC 环境)调用 CreateThread 函数和相关的同步函数,模拟实现“生产者-消费者”问题。“生产者-消费者”模拟实验的具体要求见后面附件。 定义全局变量 生产者进程 消费者进程 创建两个生产者线程、三个消费者线程..._在windows环境下,利用高级语言编程环境(限定为vs环境)调用createthread函数实现“