④. 实战:电商比价需求
①. 最近公司做了一个比价的需求案列,要求我们去爬取别的网站比如果某一本书买多少,
我们将数据拿到(以JSON的形式), 将它存入redis的zset中,保证数据没有重复的大概数据
有1w条,我自己在想,1w条全网扫描一遍,这样能做,性能不高,我们 可以使用JUC中的
CompletableFuture它可以做异步多线程并发,不阻塞,我用它从多少s–优化到了多少s。
CompletableFuture默认使用ForkJoinPool线程池,我也优化了线程池,自己写了
ThreadPoolExecutor,把自定义的线程池用在CompletableFuture中,把网站的挨个挨个的调度变成了异步编排,这样性能极佳提升
②. 案例说明:电商比价需求
同一款产品,同时搜索出同款产品在各大电商的售价;
同一款产品,同时搜索出本产品在某一个电商平台下,各个入驻门店的售价是多少
出来结果希望是同款产品的在不同地方的价格清单列表,返回一个List
《mysql》 in jd price is 88.05
《mysql》 in pdd price is 86.11
《mysql》 in taobao price is 90.43
③. 代码展示
public class CompletableFutureNetMallDemo { static List<NetMall> list = Arrays.asList( new NetMall("jd"), new NetMall("pdd"), new NetMall("taobao"), new NetMall("dangdangwang"), new NetMall("tmall") ); //同步 ,step by step /** * List<NetMall> ----> List<String> * @param list * @param productName * @return */ public static List<String> getPriceByStep(List<NetMall> list,String productName) { return list .stream(). map(netMall -> String.format(productName + " in %s price is %.2f", netMall.getMallName(), netMall.calcPrice(productName))) .collect(Collectors.toList()); } //异步 ,多箭齐发 /** * List<NetMall> ---->List<CompletableFuture<String>> ---> List<String> * @param list * @param productName * @return */ public static List<String> getPriceByASync(List<NetMall> list,String productName) { return list .stream() .map(netMall -> CompletableFuture.supplyAsync(() -> String.format(productName + " is %s price is %.2f", netMall.getMallName(), netMall.calcPrice(productName)))) .collect(Collectors.toList()) .stream() .map(CompletableFuture::join) .collect(Collectors.toList()); } public static void main(String[] args) { Stream<NetMall> netMallStream = list.stream().map(s -> s); long startTime = System.currentTimeMillis(); List<String> list1 = getPriceByStep(list, "mysql"); for (String element : list1) { System.out.println(element); } long endTime = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime - startTime) +" 毫秒"); System.out.println(); long startTime2 = System.currentTimeMillis(); List<String> list2 = getPriceByASync(list, "mysql"); for (String element : list2) { System.out.println(element); } long endTime2 = System.currentTimeMillis(); System.out.println("----costTime: "+(endTime2 - startTime2) +" 毫秒"); } } class NetMall { private String mallName; public String getMallName() { return mallName; } public NetMall(String mallName) { this.mallName = mallName; } public double calcPrice(String productName) { //检索需要1秒钟 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0); } } /* mysql in jd price is 110.59 mysql in pdd price is 110.23 mysql in taobao price is 110.04 mysql in dangdangwang price is 110.08 mysql in tmall price is 109.91 ----costTime: 5030 毫秒 mysql is jd price is 109.07 mysql is pdd price is 109.47 mysql is taobao price is 109.04 mysql is dangdangwang price is 110.09 mysql is tmall price is 110.72 ----costTime: 1021 毫秒 **/