业务场景

在很多项目中,都有类似数据汇总的业务场景,查询今日注册会员数,在线会员数,订单总金额,支出总金额等。。。这些业务通常都不是存在同一张表中,我们需要依次查询出来然后封装成所需要的对象返回给前端。那么在此过程中,就可以把这个接口中“大任务”拆分成N个小任务,异步执行这些小任务,等到最后一个小任务执行完,把所有任务的执行结果封装到返回结果中,统一返回到前端展示。

同步执行

首先看看同步执行的代码

public class Test {

    @Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
class Result {
/**
* 在线人数
*/
Integer onlineUser; /**
* 注册人数
*/
Integer registered; /**
* 订单总额
*/
BigDecimal orderAmount; /**
* 支出总额
*/
BigDecimal outlayAmount;
} @org.junit.Test
public void collect() {
System.out.println("数据汇总开始");
long startTime = System.currentTimeMillis();
Integer onlineUser = queryOnlineUser();
Integer registered = queryRegistered();
BigDecimal orderAmount = queryOrderAmount();
BigDecimal outlayAmount = queryOutlayAmount();
Result result = new Result(onlineUser, registered, orderAmount, outlayAmount);
long endTime = System.currentTimeMillis();
System.out.println("获取汇总数据结束,result = " + result);
System.out.println("总耗时 = " + (endTime - startTime) + "毫秒");
} public Integer queryOnlineUser() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询在线人数 耗时2秒");
return 10;
} public Integer queryRegistered() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询注册人数 耗时2秒");
return 10086;
} public BigDecimal queryOrderAmount() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询订单总额 耗时3秒");
return BigDecimal.valueOf(2000);
} public BigDecimal queryOutlayAmount() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询支出总额 耗时3秒");
return BigDecimal.valueOf(1000);
} }

执行时长想必大家都能够想得到,理所应当是10秒以上

数据汇总开始
查询在线人数 耗时2秒
查询注册人数 耗时2秒
查询订单总额 耗时3秒
查询支出总额 耗时3秒
获取汇总数据结束,result = Test.Result(onlineUser=10, registered=10086, orderAmount=2000, outlayAmount=1000)
总耗时 = 10008毫秒

异步执行

下面换成异步执行,用java8的parallelStream(并行流),这里为什么不用Thread呢,这里有一个注意点,我们需要获取所有所有子任务执行完的时间点,在这个时间点之后才能将结果封装返回,Thread没有办法满足,这里parallelStream和函数式接口就登场了。

java8的特性之一 —— lambda表达式,就是配合函数式接口使用的。

java8内置了四大核心函数式接口:

1、Consumer<T>   : 消费型接口    void accept(T t);

2、Supplier<T>      : 供给型接口    T get();

3、Function<T,R>   : 函数型接口    R apply(T t);

4、Predicate<T>    : 断言型接口    boolean test(T t);

这四大核心函数式接口其下还有很多子接口,基本上能满足日常项目所用,这里扯远了。。   直接上代码。

这里我们需要使用的是Runable接口,是无参无返回值的一个接口。在实际场景中,可能有时间范围之类的查询参数的,则可以根据不同业务使用不同的接口。这种方式也可以用Future接口去实现,有兴趣的可以试一试,这里就不多做叙述了。

@org.junit.Test
public void collect() {
System.out.println("数据汇总开始");
long startTime = System.currentTimeMillis();
Result result = new Result();
List<Runnable> taskList = new ArrayList<Runnable>() {
{
add(() -> result.setOnlineUser(queryOnlineUser()));
add(() -> result.setRegistered(queryRegistered()));
add(() -> result.setOrderAmount(queryOrderAmount()));
add(() -> result.setOutlayAmount(queryOutlayAmount()));
}
};
taskList.parallelStream().forEach(v -> v.run());
long endTime = System.currentTimeMillis();
System.out.println("获取汇总数据结束,result = " + result);
System.out.println("总耗时 = " + (endTime - startTime) + "毫秒");
}

执行结果,由于四个子任务都是并行的,效率直接提升了三倍,如果子任务越多的话提升效果越明显。

数据汇总开始
查询在线人数 耗时2秒
查询注册人数 耗时2秒
查询订单总额 耗时3秒
查询支出总额 耗时3秒
获取汇总数据结束,result = Test.Result(onlineUser=10, registered=10086, orderAmount=2000, outlayAmount=1000)
总耗时 = 3079毫秒

总结

1.parallelStream是异步编程的好帮手,在使用过程中一定要注意线程安全的问题。

2.以上这种方式只能用在没有事务的业务中,因为在多线程中,事务是不共享的。

java8的parallelStream提升数倍查询效率的更多相关文章

  1. java8中parallelStream提升数倍查询效率是怎样实现的,来看看这篇文章

    作者:我恰芙蓉王 原文:https://www.cnblogs.com/-tang/p/13283216.html 业务场景 在很多项目中,都有类似数据汇总的业务场景,查询今日注册会员数,在线会员数, ...

  2. 分布式协同AI基准测试项目Ianvs:工业场景提升5倍研发效率

    摘要:全场景可扩展的分布式协同AI基准测试项目 Ianvs(雅努斯),能为算法及服务开发者提供全面开发套件支持,以研发.衡量和优化分布式协同AI系统. 本文分享自华为云社区<KubeEdge|分 ...

  3. MySQL 5.7 优化SQL提升100倍执行效率的深度思考(GO)

    系统环境:微软云Linux DS12系列.Centos6.5 .MySQL 5.7.10.生产环境,step1,step2是案例,精彩的剖析部分在step3,step4. 1.慢sql语句大概需要13 ...

  4. atitit.提升2--3倍开发效率--cbb体系的建设..

    atitit.提升开发效率--cbb体系的建设.. #--提升倍数,大概2--3倍.. #---cbb的内容 知识的,expt的,经验的技术的部件的问题库的角度.. #---cbb的层次,tech l ...

  5. 可以提升3倍开发效率的 Intellij IDEA快捷键大全汇总(2019)

    整理了一下IDEA的常用快捷键,可以打印出来或者弄成图片设置为桌面,为广大的程序员们节省更多的时间去谈恋爱. 常用快捷键1 Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表达式 ...

  6. 阿里云SaaS加速器“宜搭”发布宜搭Plus提升6倍研发效率

    9月26日,在杭州云栖大会上,阿里云SaaS加速器的“底座”——“宜搭”正式发布“宜搭Plus”低代码开发平台.开发复杂企业业务系统所需要的领域数据模型.逻辑&服务编排.专业UI页面设计等,都 ...

  7. 查询效率提升10倍!3种优化方案,帮你解决MySQL深分页问题

    开发经常遇到分页查询的需求,但是当翻页过多的时候,就会产生深分页,导致查询效率急剧下降. 有没有什么办法,能解决深分页的问题呢? 本文总结了三种优化方案,查询效率直接提升10倍,一起学习一下. 1. ...

  8. 使用Apache Spark 对 mysql 调优 查询速度提升10倍以上

    在这篇文章中我们将讨论如何利用 Apache Spark 来提升 MySQL 的查询性能. 介绍 在我的前一篇文章Apache Spark with MySQL 中介绍了如何利用 Apache Spa ...

  9. PostgreSQL LIKE 查询效率提升实验<转>

    一.未做索引的查询效率 作为对比,先对未索引的查询做测试 EXPLAIN ANALYZE select * from gallery_map where author = '曹志耘'; QUERY P ...

随机推荐

  1. 01 . Docker原理部署及常用操作命令

    Docker的来源及构造: 容器是一种基础工具:泛指任何用于容纳其他物品的工具,可以部分或完全封闭,被用于容纳,储存,运输物品: 物品可以被放置在容器中,而容器可以保护内容物: 人类使用容器的历史有十 ...

  2. 041.Kubernetes集群网络-K8S网络策略

    一 Kubernetes网络策略 1.1 策略说明 为实现细粒度的容器间网络访问隔离策略,Kubernetes发布Network Policy,目前已升级为networking.k8s.io/v1稳定 ...

  3. 一个简单的Shell脚本(解决windows上文本在macos上乱码问题)

    之所以有这一篇文章,是因为之前我写过的一篇文章:“解决Mac上打开txt文件乱码问题”:传送门: https://www.cnblogs.com/chester-cs/p/11784079.html ...

  4. 【JMeter_08】JMeter逻辑控制器__While控制器<While Controller>

    While控制器<While Controller> 业务逻辑: 当条件为非false时,执行该节点下的脚本内容,判断条件包括数字.null.空白.字母.符号.true. 当条件为fals ...

  5. 2.WebPack初始化

    一.Package.json 在项目中输入: npm init 之后会提示你一步一步输入信息,我输入的信息如下: 生成的Package.json文件如下 我们也可以在初始时省略这些步骤,让脚本使用默认 ...

  6. Dubbo想要个网关怎么办?试试整合Spring Cloud Gateway

    一.背景 在微服务架构中 API网关 非常重要,网关作为全局流量入口并不单单是一个反向路由,更多的是把各个边缘服务(Web层)的各种共性需求抽取出来放在一个公共的"服务"(网关)中 ...

  7. 面试官:你精通多少种语言的 Hello World?

    Hello World,是程序员入门编程语言的第一课.不论是C.C++还是Java ,我们写的第一个程序就是它了,还记得小编在大一C语言课上,花了一整节课时间才把它打印到控制台上.万事开头难啊,相信看 ...

  8. Python实用笔记 (5)使用dictionary和set

    dictionary 通过键值存储,具有极快的查找速度,但占用空间比list大很多 举个例子,假设要根据同学的名字查找对应的成绩,如果用list实现,需要两个list: names = ['Micha ...

  9. Vue.js 组件复用和扩展之道

    软件编程有一个重要的原则是 D.R.Y(Don't Repeat Yourself),讲的是尽量复用代码和逻辑,减少重复.组件扩展可以避免重复代码,更易于快速开发和维护.那么,扩展 Vue 组件的最佳 ...

  10. 使用scrapy实现去重,使用Redis实现增量爬取

    面试场景: 要求对正在爬取的内容与mysql数据库中的数据进行比较去重 解决方式: 通过Redis来作为中间件,通过url来确保爬过的数据不会再爬,做到增量爬取. Redis数据库其实就是一个中间件, ...