作者:我恰芙蓉王

原文:https://www.cnblogs.com/-tang/p/13283216.html

业务场景

在很多项目中,都有类似数据汇总的业务场景,查询今日注册会员数,在线会员数,订单总金额,支出总金额等。。。这些业务通常都不是存在同一张表中,我们需要依次查询出来然后封装成所需要的对象返回给前端。那么在此过程中,就可以把这个接口中“大任务”拆分成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 : 消费型接口 void accept(T t);

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

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

4、Predicate : 断言型接口 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.以上这种方式只能用在没有事务的业务中,因为在多线程中,事务是不共享的。

最后

私信回复 资料 领取一线大厂Java面试题总结+阿里巴巴泰山手册+各知识点学习思维导+一份300页pdf文档的Java核心知识点总结!

这些资料的内容都是面试时面试官必问的知识点,篇章包括了很多知识点,其中包括了有基础知识、Java集合、JVM、多线程并发、spring原理、微服务、Netty 与RPC 、Kafka、日记、设计模式、Java算法、数据库、Zookeeper、分布式缓存、数据结构等等。

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

  1. java8的parallelStream提升数倍查询效率

    业务场景 在很多项目中,都有类似数据汇总的业务场景,查询今日注册会员数,在线会员数,订单总金额,支出总金额等...这些业务通常都不是存在同一张表中,我们需要依次查询出来然后封装成所需要的对象返回给前端 ...

  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. mysql中存储字段类型的查询效率

    检索性能从快到慢的是(此处是听人说的): 第一:tinyint,smallint,mediumint,int,bigint第二:char,varchar第三:NULL 解释(转载): 整数类型1.TI ...

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

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

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

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

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

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

  8. union all 取代 select中的case when 提高查询效率

    首先union all不是适用于所有情况,其次,case when的可读性肯定要强.所以在不是特别在意性能的情况下, 可以考虑用case when. 再者,不是所有情况下的union all都要比ca ...

  9. Java7与Java8中的HashMap和ConcurrentHashMap知识点总结

    JAVA7 Java7的ConcurrentHashMap里有多把锁,每一把锁用于其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率呢.这 ...

随机推荐

  1. redis cluster集群中键的分布算法

    Redis Cluster Redis Cluster是Redis的作者 Antirez 提供的 Redis 集群方案 —— 官方多机部署方案,每组Redis Cluster是由多个Redis实例组成 ...

  2. Python3-os模块-操作系统的各种接口

    Python3中的os模块提供了一个便携的方式去使用操作系统的相关功能 os.name 返回导入的操作系统相关模块的名字,如 posix(unix/linux),nt(windows)等 os.env ...

  3. Linux文件权限学习笔记

    文件权限共10个字符,第一个字符表示该文件是[文件夹]或[文件]——如果是字符“d"则表示该文件是文件夹:如果是字符“-”则表示是文件. 后九个字符,三个一组,共三组,分别表示[所有者权限] ...

  4. web页面弹出遮罩层,通过js或css禁止蒙层底部页面跟随滚动

    场景概述 弹窗是一种常见的交互方式,而蒙层是弹窗必不可少的元素,用于隔断页面与弹窗区块,暂时阻断页面的交互.但是,在蒙层元素中滑动的时候,滑到内容的尽头时,再继续滑动,蒙层底部的页面会开始滚动,显然这 ...

  5. 简单的JdbcUtil 类

    import java.sql.*; /** JDBC工具类 */ public class JdbcUtil { /** * 获取数据库连接对象并返回 * * @return Connection对 ...

  6. 查看windows操作系统的默认编码

    转自:https://blog.csdn.net/zp357252539/article/details/79084480/ 在Windows平台下,进入DOS窗口,输入:chcp 可以得到操作系统的 ...

  7. [BSidesCF 2020]Had a bad day

    [BSidesCF 2020]Had a bad day 测试 一些猫狗的图片加上url有传参,测试到文件包含时报错了. 使用php伪协议: php伪协议 php://fliter/read=conv ...

  8. requests接口自动化6-Body里json格式数据形式的post请求:json

    Body里json格式数据形式的post请求:用json传参 fiddler里请求响应内容: 传递的json数据 [{"stepId":"0","ca ...

  9. requests接口自动化1-json序列化与反序列化

    json序列化与反序列化: 序列化:将对象转换为json字符串 反序列化:将json字符串转换为对象,比如转换为python里的字典 import json #定义字典 dict1={'usernam ...

  10. java 数据结构(十):Collection子接口:Set接口

    1. 存储的数据特点:无序的.不可重复的元素具体的: 以HashSet为例说明:1. 无序性:不等于随机性.存储的数据在底层数组中并非照数组索引的顺序添加,而是根据数据的哈希值决定的.2. 不可重复性 ...