Java并发编程—CompletableFuture的异步执行案例

        在博主前几篇博客中,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){
        //模拟检索用时1s
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    	//高并发多线程使用ThreadLocalRandom
        return ThreadLocalRandom.current().nextDouble()*2+commodityName.charAt(0);
    }

}

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

public class CSDNCompletableFutureDemo {

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




}

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

 /*一个一个的从商城进行搜索一个商品,然后返回一个格式化好了的集合*/
    public static List<String> stepSearch(List<ShoppMall> 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<String> 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<String> synSearch(List<ShoppMall> 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<String> search1 = stepSearch(list, "茅台");
        List<String> 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表达式,需要大家把代码运行看一下效果就可以理解

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值