乐趣区

关于java:java8中parallelStream提升数倍查询效率是怎样实现的来看看这篇文章

作者:我恰芙蓉王

原文:https://www.cnblogs.com/-tang…

业务场景

在很多我的项目中,都有相似数据汇总的业务场景,查问今日注册会员数,在线会员数,订单总金额,收入总金额等。。。这些业务通常都不是存在同一张表中,咱们须要顺次查问进去而后封装成所须要的对象返回给前端。那么在此过程中,就能够把这个接口中“大工作”拆分成 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. 以上这种形式只能用在没有事务的业务中,因为在多线程中,事务是不共享的。

最初

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

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

退出移动版