Java并发编程—CompletableFuture的异步执行案例
创始人
2024-03-22 10:24:29
0

        在博主前几篇博客中,https://blog.csdn.net/qq_52545155/article/details/128167519?spm=1001.2014.3001.5501,给大家分享了关于多线程中异步任务的执行和一些相关概念,在这篇博客中,主要是通过一个实际的案例让大家对于CompletableFuture的用法有一个深入的理解

🍏一、需求分析

        临近过年了,很多铁子都有购物的需求,那么大家肯定想花更少的钱去买相同的一个产品,例如茅台酒在不同的购物平台或者不同的商家里面价格是不一样的,例如:

🍕jd:

🍕tb:

       图中这些价格都是不一样的,所以大家就会有一个需求,能不能把这个当作一个程序进行一个数据统计,统计出不同平台的茅台价格,然后自己根据价格、商家来购买,这个例子大家都明白,其实在工作中也有很多这种的需求,那么针对这种需要统计的需求业务我们该怎么去做呢?

🍏二、方案设计

        相信很多铁子有心里有方案:

        🍄1、一个一个的进行记录,或者用爬虫去爬

        🍄2、用异步多线程进行统计,这这里博主会分享第二种的实践方式

🍏三、代码展示

        前面是举个例子,这个并不会去搜刮数据哈,大家对于接口api的调用可以自行补充,主要分享思维,商城在代码种是以对象实体存在的;    

🍄1、先准备一个商城公共类

class ShoppMall{private String mallName;public String getMallName() {return mallName;}public ShoppMall(String mallName) {this.mallName = mallName;}/*商城存在了,这里提供一个根据输入的商品名返回一个价格的方法*/public Double getPrice(String commodityName){//模拟检索用时1stry {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}//高并发多线程使用ThreadLocalRandomreturn ThreadLocalRandom.current().nextDouble()*2+commodityName.charAt(0);}}

🍄2、业务开始前还需要实例化几个具体的商城对象出来,这样才能通过上面的getPrice()方法获取到价格

public class CSDNCompletableFutureDemo {//实例化几个商城对象,放到集合中private static List list= Arrays.asList(new ShoppMall("jd"),new ShoppMall("tb"),new ShoppMall("pdd"));}

🍄3、一个商城一个商城进行搜索的操作,代码如下:

 /*一个一个的从商城进行搜索一个商品,然后返回一个格式化好了的集合*/public static List stepSearch(List list,String comName){return list.stream().map(mall -> {System.out.println(mall.getMallName() + "正在查找" + comName);return String.format("%s 的 %s 价格是%.2f", mall.getMallName(), comName, mall.getPrice(comName));}).collect(Collectors.toList());}

🍄4、这个时候我们可以先对其进行一个测试,看看效果如何:

public static void main(String[] args) {long startTime = System.currentTimeMillis();List search1 = stepSearch(list, "茅台");for (String s : search1) {System.out.println(s);}System.out.println("本次用时"+(System.currentTimeMillis()-startTime)+"毫秒");}

效果如下:

🚗总结:这里每一个商城搜索都用了1s,然后加上其他的耗时,一共是3061毫秒,代码着我有多少个平台,至少就要花n+秒的时间,显然这个很不能让人接收,那么在我们用Compleatable如何去实现呢,接着往下看;

🍄5、用异步多线程进行执行,代码如下:

/*用CompletableFuture异步多线程进行搜索,然后返回一个格式化好了的集合*/public static List synSearch(List list, String comName) {return list.stream().map(mall -> {System.out.println(mall.getMallName() + "正在查找" + comName);return CompletableFuture.supplyAsync(() -> {return String.format("%s 的 %s 价格是%.2f", mall.getMallName(), comName, mall.getPrice(comName));});}).collect(Collectors.toList()).stream().map(CompletableFuture::join).collect(Collectors.toList());}

运行代码:

    public static void main(String[] args) {long startTime = System.currentTimeMillis();
//        List search1 = stepSearch(list, "茅台");List search1 = synSearch(list, "茅台");for (String s : search1) {System.out.println(s);}System.out.println("本次用时" + (System.currentTimeMillis() - startTime) + "毫秒");}

效果图:

 

🚗总结:每个商城检索要一秒,而这种方式相当于是在一秒钟,多个商城同时进行搜索,然后将结果进行了返回,达到了万箭齐发的效果,这也正是我们想要的。

🍏四、总结

        🍄1、博主分别用了2种方式,传统方式的one by one一个一个的搜索是非常耗时且效率低下

        🍄2、采用多线程同时进行搜索,节约时间节约成本,是我们想要的效果

        🍄3、实现功能是每个程序员都要完成的,但是最终都是靠性能说服别人,这里是3个商城,普通的就要3s+,而异步执行只需要一秒即可完成,假如我多实例化一个商城,普通方式就需要多一秒,而异步还是只要一秒,显然比one by one来得更有力,这就是为啥高并发这么使人神往;

        🍄4、当商城实例足够多了的话,可以不选择用CompletableFuture自带的线程池,可以自定义线程池然后进行传入使用。还可以分批次进行线程执行,都是一些优化手段;

         🍄4、代码很多是Stream流和Lambda表达式,需要大家把代码运行看一下效果就可以理解

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...