Asynchronously orchestrated CompletableFuture using

Business scenario: data query on product details page

Insert image description here

business analysis

Because there are many steps to query product details, and part of the data needs to be called remotely, an asynchronous method can be used in this scenario where there are many steps and is time-consuming.

Example:
For step-by-step query in the normal method, the total time consumption = the sum of the time consumption of the 5 steps (0.5s+0.5s+1s+1.5s+1s=the total time consumption is 4.5s). In the asynchronous method, the total time consumption
= the maximum step time consumption time (1.5s)

However, the business here cannot be done directly in an asynchronous manner, because steps 3, 4, and 5 require the results of step 1, and step 2 does not need to use the results of step 1. So how can we ensure efficiency? What about using asynchronous operations? Another core point is how to obtain the results of asynchronous operations?
We know that to obtain asynchronous results, we can use Future to get(), block the thread to obtain the results, or obtain the results through polling. Although Future can obtain results, it is inefficient and consumes resources. Here we use the implementation class ComletableFuture of the Future interface to implement asynchronous programming.
Advantages of ComletableFuture : (1) The callback function obtains asynchronous calculation results (2) The order of business can be designed (3) API is rich

1. Package result design

@Data
public class SkuItemVo {
    
    
    private boolean hasStock = true;
    //1.sku基本信息:title,price
    SkuInfoEntity info;
    //2.sku轮播图片
    List<SkuImagesEntity> images;
    //3.销售版本组合:颜色、版本、内存——黑色;白色;蓝色
    List<ItemSaleAttrsVo> saleAttr;
    //4.spu的商品介绍(sku共享):销售属性+展示图
    SpuInfoDescEntity desc;
    //5.规格与包装:所有属性分组下的所有属性
    List<SkuItemSaleAttrVo> groupAttrs;

    @Data
    public static class ItemSaleAttrsVo{
    
    
        private Long attrId;
        private String attrName;
        //当前属性有多少种版本:黑色,白色,蓝色
        private List<AttrValueWithSkuIdVo> attrValues;

    }

    @Data
    public static class SkuItemSaleAttrVo{
    
    
        private String groupName;
        private List<SpuBaseAttrVo> attrs;
    }

    @Data
    public static class SpuBaseAttrVo{
    
    
        private String attrName;
        private String attrValue;
    }

}

2. Custom thread pool

@Configuration
public class MyThreadConfig {
    
    

    /**
     *    int corePoolSize, 核心线程数
     *    int maximumPoolSize,最新线程数
     *    long keepAliveTime, 空闲线程剩余时间
     *    TimeUnit unit,时间单位
     *    BlockingQueue<Runnable> workQueue 阻塞队列
     *    ThreadFactory threadFactory, 线程工厂
     *    RejectedExecutionHandler handler 拒绝策略
     */
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool){
    
    
        return new ThreadPoolExecutor(
                pool.getCoreSize(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),//最多存储10万异步任务
                Executors.defaultThreadFactory(),//默认工厂
                new ThreadPoolExecutor.AbortPolicy());//抛弃策略
    }
}

3. @ConfigurationProperties custom properties and can be used in configuration files

@ConfigurationProperties(prefix = "gulimall.thread")//元数据处理器,配置问题中书写时有提示
@Component//放在容器中
@Data
public class ThreadPoolConfigProperties {
    
    
    private Integer coreSize;
    private Integer maxSize;
    private Integer KeepAliveTime;
}

application.properties

gulimall.thread.core-size=20
gulimall.thread.max-size=200
gulimall.thread.keep-alive-time=10

4. Use of asynchronous orchestration

	//导入线程池
	@Autowired
    ThreadPoolExecutor executor;

	//返回详情页信息
    @Override
    public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {
    
    
        SkuItemVo skuItemVo = new SkuItemVo();

        /**
         * 1.为什么一定要使用自定义的线程池?
         * 2.执行策略:
         *  1->3,4,5
         *  2
         * 3.allof()作用
         */
        //1.sku基本信息:title,price
        CompletableFuture<SkuInfoEntity> infoFture = CompletableFuture.supplyAsync(new Supplier<SkuInfoEntity>() {
    
    
            @Override
            public SkuInfoEntity get() {
    
    
                SkuInfoEntity info = getById(skuId);
                skuItemVo.setInfo(info);
                return info;
            }
        }, executor);

        //3.销售版本组合:颜色、版本、内存
        CompletableFuture<Void> saleThread = infoFture.thenAcceptAsync(new Consumer<SkuInfoEntity>() {
    
    
            @Override
            public void accept(SkuInfoEntity skuInfoEntity) {
    
    
                List<SkuItemVo.ItemSaleAttrsVo> saleAttr = skuSaleAttrValueService.getSkuSaleAttrValue(skuInfoEntity.getSpuId());
                skuItemVo.setSaleAttr(saleAttr);
            }
        }, executor);

        //4.spu的商品介绍(sku共享):销售属性+展示图
        CompletableFuture<Void> descThread = infoFture.thenAcceptAsync(new Consumer<SkuInfoEntity>() {
    
    
            @Override
            public void accept(SkuInfoEntity skuInfoEntity) {
    
    
                SpuInfoDescEntity desc = spuInfoDescService.getById(skuInfoEntity.getSpuId());
                skuItemVo.setDesc(desc);
            }
        }, executor);

        //5.规格与包装:所有属性分组下的所有属性
        CompletableFuture<Void> attrThread = infoFture.thenAcceptAsync(new Consumer<SkuInfoEntity>() {
    
    
            @Override
            public void accept(SkuInfoEntity skuInfoEntity) {
    
    
                Long catalogId = skuInfoEntity.getCatalogId();
                List<SkuItemVo.SkuItemSaleAttrVo> groupAttrs = attrGroupService.getAttrGroupWithAttrsBySpuId(skuInfoEntity.getSpuId(), catalogId);
                skuItemVo.setGroupAttrs(groupAttrs);
            }
        }, executor);

        //2.sku轮播图片
        CompletableFuture<Void> imagesThread = CompletableFuture.runAsync(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                List<SkuImagesEntity> skuImagesEntities = skuImagesService.getImagesBySkuId(skuId);
                skuItemVo.setImages(skuImagesEntities);
            }
        }, executor);

        //等待所有任务执行结束
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(infoFture,saleThread, descThread, attrThread, imagesThread);
        voidCompletableFuture.get();

        return skuItemVo;
    }

Guess you like

Origin blog.csdn.net/weixin_44847885/article/details/131289360