java 高地位倒排拼接_java高并发系列 - 第27天:实战篇,接口性能成倍提升,让同事刮目相看,现学现用...

这是java高并发系列第27篇文章。

开发环境:jdk1.8。

案例讲解

电商app都有用过吧,商品详情页,需要给他们提供一个接口获取商品相关信息:

商品基本信息(名称、价格、库存、会员价格等)

商品图片列表

商品描述信息(描述信息一般是由富文本编辑的大文本信息)

数据库中我们用了3张表存储上面的信息:

商品基本信息表:t_goods(字段:id【商品id】、名称、价格、库存、会员价格等)

商品图片信息表:t_goods_imgs(字段:id、goods_id【商品id】、图片路径),一个商品会有多张图片

商品描述信息表:t_goods_ext(字段:id,goods_id【商品id】、商品描述信息【大字段】)

这需求对于大家来说很简单吧,伪代码如下:

public Map 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 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 goodsDetail(long goodsId) throws ExecutionException, InterruptedException {

Map result = new HashMap<>();

//异步获取商品基本信息

Future gooldsDetailModelFuture = executorService.submit(() -> goodsDetailModel(goodsId));

//异步获取商品图片列表

Future> goodsImgsModelListFuture = executorService.submit(() -> goodsImgsModelList(goodsId));

//异步获取商品描述信息

Future 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 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高并发系列目录

第1天:必须知道的几个概念

第2天:并发级别

第3天:有关并行的两个重要定律

第4天:JMM相关的一些概念

第5天:深入理解进程和线程

第6天:线程的基本操作

第7天:volatile与Java内存模型

第8天:线程组

第9天:用户线程和守护线程

第10天:线程安全和synchronized关键字

第11天:线程中断的几种方式

第12天JUC:ReentrantLock重入锁

第13天:JUC中的Condition对象

第14天:JUC中的LockSupport工具类,必备技能

第15天:JUC中的Semaphore(信号量)

第16天:JUC中等待多线程完成的工具类CountDownLatch,必备技能

第17天:JUC中的循环栅栏CyclicBarrier的6种使用场景

第18天:JAVA线程池,这一篇就够了

第19天:JUC中的Executor框架详解1

第20天:JUC中的Executor框架详解2

第21天:java中的CAS,你需要知道的东西

第22天:JUC底层工具类Unsafe,高手必须要了解

第23天:JUC中原子类,一篇就够了

第24天:ThreadLocal、InheritableThreadLocal(通俗易懂)

第25天:掌握JUC中的阻塞队列

java高并发系列连载中,总计估计会有四五十篇文章。

阿里p7一起学并发,公众号:路人甲java,每天获取最新文章!

原文出处:https://www.cnblogs.com/itsoku123/p/11364035.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值