[ビジネス機能 第93章] マイクロサービス-スプリングクラウド-マルチスレッド-非同期処理-非同期オーケストレーション-CompletableFutrue-実用アプリケーション

非同期処理オーケストレーション

  CompletableFutureの非同期オーケストレーション処理を商品詳細クエリの箇所に実装できます。

ビジネス分析によると、3.4.5 データ インターフェイスの入力パラメータ情報は 1 データ インターフェイス (skuid) の戻り情報から取得する必要があるため、1 3 4 5 シリアル スレッドを設計でき、3 4 5 は 1 と 2 に依存します。 1 の実行が完了するまで待つ必要があります
。 2 インターフェイス データには関係がないため、上記のスレッドと並列関係があるため、
1 2 インターフェイス データは並列実行されますが、非同期オーケストレーション設計では 3 4 5 と 1 はシリアルに実行されます。この処理により、
元の 5 つのインターフェイスが 2 秒かかるとすると、合計時間は 10 秒になります。インターフェイス 1 と 2 が並行して実行され、さらに 3、4、5 も実行されるため、時間は短縮されます。並行して。したがって、確実に大幅な時間短縮が可能となる。
画像.png

最初にスレッド プールを定義します

 // 第一种获取的方式
 //ExecutorService service = Executors.newFixedThreadPool(10);
 // Executors.newCachedThreadPool()
 // Executors.newScheduledThreadPool() 定时任务的线程池
 // Executors.newSingleThreadExecutor(); // 线程池中永远只有一个线程去处理,并发的情况下会被变为同步的处理

 // 第二种方式: 直接new ThreadPoolExecutor()对象,并且手动的指定对应的参数
 // corePoolSize:线程池的核心线程数量 线程池创建出来后就会 new Thread() 5个
 // maximumPoolSize:最大的线程数量,线程池支持的最大的线程数
 // keepAliveTime:存活时间,当线程数大于核心线程,空闲的线程的存活时间 8-5=3
 // unit:存活时间的单位
 // BlockingQueue<Runnable> workQueue:阻塞队列 当线程数超过了核心线程数据,那么新的请求到来的时候会加入到阻塞的队列中
 // new LinkedBlockingQueue<>() 默认队列的长度是 Integer.MAX 那这个就太大了,所以我们需要指定队列的长度
 // threadFactory:创建线程的工厂对象
 // RejectedExecutionHandler handler:当线程数大于最大线程数的时候会执行的淘汰策略
@Configuration
public class MyThreadPoolConfig {
    
    

    @Bean
    public ThreadPoolExecutor threadPoolExecutor()
    {
    
    
        return new ThreadPoolExecutor(20
                ,200
                ,10
                , TimeUnit.SECONDS
                ,new LinkedBlockingQueue(10000)
                , Executors.defaultThreadFactory()
                ,new ThreadPoolExecutor.AbortPolicy()
        );
    }
}

具体的な手配処理

//注入线程配置类的线程池  用于服务方法接口的线程创建所需
@Autowired
    ThreadPoolExecutor threadPoolExecutor;

@Override
    public SpuItemVO item(Long skuId) throws ExecutionException, InterruptedException {
    
    
        SpuItemVO vo = new SpuItemVO();
        CompletableFuture<SkuInfoEntity> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
    
    
            // 1.sku的基本信息 pms_sku_info
            SkuInfoEntity skuInfoEntity = getById(skuId);
            vo.setInfo(skuInfoEntity);

            return skuInfoEntity;
        }, threadPoolExecutor);

        //thenAcceptAsync 等待前面的异步任务完成后 获取其返回值做相应的业务处理,该任务没返回值,因为主要是获取前面的sku信息做入参 不需要有返回值
        CompletableFuture<Void> saleFuture = skuInfoFuture.thenAcceptAsync((res) -> {
    
    
            // 3.获取spu中的销售属性的组合
            List<SkuItemSaleAttrVo> saleAttrs = skuSaleAttrValueService
                    .getSkuSaleAttrValueBySpuId(res.getSpuId());
            vo.setSaleAttrs(saleAttrs);
        }, threadPoolExecutor);

        CompletableFuture<Void> spuFuture = skuInfoFuture.thenAcceptAsync((res) -> {
    
    
            // 4.获取SPU的介绍
            SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
            vo.setDesc(spuInfoDescEntity);
        }, threadPoolExecutor);


        CompletableFuture<Void> groupFuture = skuInfoFuture.thenAcceptAsync((res) -> {
    
    
            // 5.获取SPU的规格参数
            List<SpuItemGroupAttrVo> groupAttrVo = attrGroupService
                    .getAttrgroupWithSpuId(res.getSpuId(), res.getCatalogId());
            vo.setBaseAttrs(groupAttrVo);
        }, threadPoolExecutor);

        //runAsync 异步任务无需返回值
        CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
    
    
            // 2.sku的图片信息pms_sku_images
            List<SkuImagesEntity> images = skuImagesService.getImagesBySkuId(skuId);
            vo.setImages(images);
        }, threadPoolExecutor);

        CompletableFuture<Void> seckillFuture = CompletableFuture.runAsync(() -> {
    
    
            // 查询商品的秒杀活动
            R r = seckillFeignService.getSeckillSessionBySkuId(skuId);
            if(r.getCode() == 0){
    
    
                SeckillVO seckillVO = JSON.parseObject(r.get("data").toString(),SeckillVO.class);
                vo.setSeckillVO(seckillVO);
            }
        }, threadPoolExecutor);


        //最后  allOF等待阻塞上面的异步任务完成后再返回值,由于3 4 5是依赖于 1skuInfoFuture异步任务完成,所以无需将1写入也可以
        CompletableFuture.allOf(saleFuture,spuFuture,imageFuture,groupFuture,seckillFuture).get();
        return vo;
    }

おすすめ

転載: blog.csdn.net/studyday1/article/details/132617513