一、線程回顧
二、CompletableFuture 異步編排
假如商品詳情頁的每個查詢,需要如下標註的時間才能完成
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { System.out.println("當前線程:" + Thread.currentThread().getId()); int i = 10 / 2; System.out.println("運行結果:" + i); }, executor);
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { System.out.println("當前線程:" + Thread.currentThread().getId()); int i = 10 / 0; System.out.println("運行結果:" + i); return i; }, executor); Integer result = future.get();
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { System.out.println("當前線程:" + Thread.currentThread().getId()); int i = 10 / 0; System.out.println("運行結果:" + i); return i; }, executor).whenComplete((res,exception) -> { //雖然能得到異常信息,但是沒法修改返回數據 System.out.println("異步任務成功完成了...結果是:" + res + "異常是:" + exception); }).exceptionally(throwable -> { //可以感知異常,同時返回默認值 return 10; });
和 complete 一樣,可對結果做最後的處理(可處理異常),可改變返回值。
/** * 方法執行完後端處理 */ CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { System.out.println("當前線程:" + Thread.currentThread().getId()); int i = 10 / 2; System.out.println("運行結果:" + i); return i; }, executor).handle((result,thr) -> { if (result != null) { return result * 2; } if (thr != null) { System.out.println("異步任務成功完成了...結果是:" + result + "異常是:" + thr); return 0; } return 0; });
thenApply 方法:當一個線程依賴另一個線程時,獲取上一個任務返回的結果,並返回當前任務的返回值。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { System.out.println("當前線程:" + Thread.currentThread().getId()); int i = 10 / 2; System.out.println("運行結果:" + i); return i; }, executor).thenApplyAsync(res -> { System.out.println("任務2啓動了..." + res); return "Hello" + res; }, executor); System.out.println("main......end....." + future.get());
兩個任務必須都完成,觸發該任務。
當兩個任務中,任意一個 future 任務完成的時候,執行任務。
allOf:等待所有任務完成
三.案例
//@EnableConfigurationProperties(ThreadPoolConfigProperties.class) @Configuration public class MyThreadConfig { @Bean public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) { return new ThreadPoolExecutor( pool.getCoreSize(), pool.getMaxSize(), pool.getKeepAliveTime(), TimeUnit.SECONDS, new LinkedBlockingDeque<>(100000), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() ); } }
2.ThreadPoolConfigProperties.java
@ConfigurationProperties(prefix = "gulimall.thread") @Component @Data public class ThreadPoolConfigProperties { private Integer coreSize; private Integer maxSize; private Integer keepAliveTime; }
3.使用異步線程
@Service("skuInfoService") public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService { @Resource private ThreadPoolExecutor executor; @Override public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException { SkuItemVo skuItemVo = new SkuItemVo(); CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> { //1、sku基本信息的獲取 pms_sku_info SkuInfoEntity info = this.getById(skuId); skuItemVo.setInfo(info); return info; }, executor); CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync((res) -> { //3、獲取spu的銷售屬性組合 List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrBySpuId(res.getSpuId()); skuItemVo.setSaleAttr(saleAttrVos); }, executor); CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync((res) -> { //4、獲取spu的介紹 pms_spu_info_desc SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId()); skuItemVo.setDesc(spuInfoDescEntity); }, executor); CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync((res) -> { //5、獲取spu的規格參數信息 List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId()); skuItemVo.setGroupAttrs(attrGroupVos); }, executor); // Long spuId = info.getSpuId(); // Long catalogId = info.getCatalogId(); //2、sku的圖片信息 pms_sku_images CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> { List<SkuImagesEntity> imagesEntities = skuImagesService.getImagesBySkuId(skuId); skuItemVo.setImages(imagesEntities); }, executor); CompletableFuture<Void> seckillFuture = CompletableFuture.runAsync(() -> { //3、遠程調用查詢當前sku是否參與秒殺優惠活動 R skuSeckilInfo = seckillFeignService.getSkuSeckilInfo(skuId); if (skuSeckilInfo.getCode() == 0) { //查詢成功 SeckillSkuVo seckilInfoData = skuSeckilInfo.getData("data", new TypeReference<SeckillSkuVo>() { }); skuItemVo.setSeckillSkuVo(seckilInfoData); if (seckilInfoData != null) { long currentTime = System.currentTimeMillis(); if (currentTime > seckilInfoData.getEndTime()) { skuItemVo.setSeckillSkuVo(null); } } } }, executor); //等到所有任務都完成 CompletableFuture.allOf(saleAttrFuture,descFuture,baseAttrFuture,imageFuture,seckillFuture).get(); return skuItemVo; } }