Java高并发专题之27、实战:你的接口太慢了需要优化
2022/5/4 22:14:18
本文主要是介绍Java高并发专题之27、实战:你的接口太慢了需要优化,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
电商接口案例讲解
电商app都有用过吧,商品详情页,需要给他们提供一个接口获取商品相关信息:
- 商品基本信息(名称、价格、库存、会员价格等)
- 商品图片列表
- 商品描述信息(描述信息一般是由富文本编辑的大文本信息)
数据库中我们用了3张表存储上面的信息:
- 商品基本信息表:t_goods(字段:id【商品id】、名称、价格、库存、会员价格等)
- 商品图片信息表:t_goods_imgs(字段:id、goods_id【商品id】、图片路径),一个商品会有多张图片
- 商品描述信息表:t_goods_ext(字段:id,goods_id【商品id】、商品描述信息【大字段】)
这需求对于大家来说很简单吧,伪代码如下:
public Map<String,Object> detail(long goodsId){ //创建一个map //step1:查询商品基本信息,放入map map.put("goodsModel",(select * from t_goods where id = #gooldsId#)); //step2:查询商品图片列表,返回一个集合放入map map.put("goodsImgsModelList",(select * from t_goods_imgs where goods_id = #gooldsId#)); //step3:查询商品描述信息,放入map map.put("goodsExtModel",(select * from t_goods_ext where goods_id = #gooldsId#)); return map;}
上面这种写法应该很常见,代码很简单,假设上面每个步骤耗时200ms,此接口总共耗时>=600毫秒,其他还涉及到网络传输耗时,估计总共会在700ms左右,此接口有没有优化的空间,性能能够提升多少?我们一起来挑战一下。
在看一下上面的逻辑,整个过程是按顺序执行的,实际上3个查询之间是没有任何依赖关系,所以说3个查询可以同时执行,那我们对这3个步骤采用多线程并行执行,看一下最后什么情况,代码如下:
package com.itsoku.chat26;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.*;/** * 跟着阿里p7学并发,微信公众号:javacode2018 */public class Demo1 { /** * 获取商品基本信息 * * @param goodsId 商品id * @return 商品基本信息 * @throws InterruptedException */ public String goodsDetailModel(long goodsId) throws InterruptedException { //模拟耗时,休眠200ms TimeUnit.MILLISECONDS.sleep(200); return "商品id:" + goodsId + ",商品基本信息...."; } /** * 获取商品图片列表 * * @param goodsId 商品id * @return 商品图片列表 * @throws InterruptedException */ public List<String> goodsImgsModelList(long goodsId) throws InterruptedException { //模拟耗时,休眠200ms TimeUnit.MILLISECONDS.sleep(200); return Arrays.asList("图1", "图2", "图3"); } /** * 获取商品描述信息 * * @param goodsId 商品id * @return 商品描述信息 * @throws InterruptedException */ public String goodsExtModel(long goodsId) throws InterruptedException { //模拟耗时,休眠200ms TimeUnit.MILLISECONDS.sleep(200); return "商品id:" + goodsId + ",商品描述信息......"; } //创建个线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); /** * 获取商品详情 * * @param goodsId 商品id * @return * @throws ExecutionException * @throws InterruptedException */ public Map<String, Object> goodsDetail(long goodsId) throws ExecutionException, InterruptedException { Map<String, Object> result = new HashMap<>(); //异步获取商品基本信息 Future<String> gooldsDetailModelFuture = executorService.submit(() -> goodsDetailModel(goodsId)); //异步获取商品图片列表 Future<List<String>> goodsImgsModelListFuture = executorService.submit(() -> goodsImgsModelList(goodsId)); //异步获取商品描述信息 Future<String> goodsExtModelFuture = executorService.submit(() -> goodsExtModel(goodsId)); result.put("gooldsDetailModel", gooldsDetailModelFuture.get()); result.put("goodsImgsModelList", goodsImgsModelListFuture.get()); result.put("goodsExtModel", goodsExtModelFuture.get()); return result; } public static void main(String[] args) throws ExecutionException, InterruptedException { long starTime = System.currentTimeMillis(); Map<String, Object> map = new Demo1().goodsDetail(1L); System.out.println(map); System.out.println("耗时(ms):" + (System.currentTimeMillis() - starTime)); }}
输出:
{goodsImgsModelList=[图1, 图2, 图3], gooldsDetailModel=商品id:1,商品基本信息...., goodsExtModel=商品id:1,商品描述信息......}耗时(ms):208
可以看出耗时200毫秒左右,性能提升了2倍,假如这个接口中还存在其他无依赖的操作,性能提升将更加显著,上面使用了线程池并行去执行3次查询的任务,最后通过Future获取异步执行结果。
整个优化过程
- 先列出无依赖的一些操作
- 将这些操作改为并行的方式
用到的技术有
- 线程池相关知识
- Executors、Future相关知识
总结
- 对于无依赖的操作尽量采用并行方式去执行,可以很好的提升接口的性能
- 大家可以在你们的系统中试试这种方法,感受一下效果,会让你感觉很爽
这篇关于Java高并发专题之27、实战:你的接口太慢了需要优化的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-15鸿蒙生态设备数量超8亿台
- 2024-05-13TiDB + ES:转转业财系统亿级数据存储优化实践
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?