在博主前几篇博客中,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) + "毫秒");
}
效果图:
🚗总结:每个商城检索要一秒,而这种方式相当于是在一秒钟,多个商城同时进行搜索,然后将结果进行了返回,达到了万箭齐发的效果,这也正是我们想要的。