本篇博客记录,自定义线程池配置,线程池+异步编排的使用。
1、编写MyThreadConfig 配置类
/**
* @author linZT
* 自定义线程池--》设置成可配置的(ThreadPoolConfigProperties); 也可以直接给固定值。
*/
//@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {
/**
* ThreadPoolConfigProperties类 已经被@component了,交给spring管理了,可以直接用
* @param threadPoolConfigProperties
* @return
*/
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties threadPoolConfigProperties){
//7大参数: 核心线程数,最大线程数,丢弃时间,阻塞队列,抛弃策略
return new ThreadPoolExecutor(threadPoolConfigProperties.getCoreSize(),
threadPoolConfigProperties.getMaxSize(),
threadPoolConfigProperties.getKeepAliveTime(), TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
}
}
2、编写可配置的线程池参数,从配置文件application.yml获取
/**
* @author linZT
* 可配置的线程池参数,从配置文件application.yml获取
*/
@ConfigurationProperties(prefix = "my.thread")
@Component
@Data
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer maxSize;
private Integer keepAliveTime;
}
3、配置文件application.yml
my:
thread:
core-size: 20
max-size: 200
keep-alive-time: 10
4、实例:使用线程池 + 异步编排。 效率冲冲冲!
/**
* @author linZT
*/
@Slf4j
@Service
public class CartServiceImpl implements CartService {
/**
* 给当前容器注入线程池,做异步任务
*/
@Autowired
ThreadPoolExecutor executor;
/**
* 根据id查询商品详细信息
* 使用异步编排 completableFuture
*/
public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {
SkuItemVo skuItemVo = new SkuItemVo();
//supplyAsync有返回值
CompletableFuture<SkuInfoEntity> infoEntityCompletableFuture = CompletableFuture.supplyAsync(() -> {
//1 sku基本信息
SkuInfoEntity infoEntity = getById(skuId);
skuItemVo.setInfo(infoEntity);
return infoEntity;
}, executor);
/**
* 1.2.3是并行处理。需要先获取1的结果,采用异步编排的好处就是不用顺序执行,提高效率。
*/
//需要第一个的返回结果 res上一个的返回结果 1.1
CompletableFuture<Void> attrFuture = infoEntityCompletableFuture.thenAcceptAsync((res) -> {
//3 获取sku的销售属性组合
List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrsBySpuId(res.getSpuId());
skuItemVo.setSaleAttr(saleAttrVos);
}, executor);
//需要第一个的返回结果 res上一个的返回结果 1.2
CompletableFuture<Void> descFuture = infoEntityCompletableFuture.thenAcceptAsync((res) -> {
//4 spu描述信息
SpuInfoDescEntity description = descService.getById(res.getSpuId());
skuItemVo.setDesp(description);
}, executor);
//需要第一个的返回结果 res上一个的返回结果 1.3
CompletableFuture<Void> groupFuture = infoEntityCompletableFuture.thenAcceptAsync((res) -> {
//5 规格参数 一个组 下面有多对的k-v
//Long catalogId = infoEntity.getCatalogId();
List<SpuItemBaseAttrGroupVo> spuItemBaseAttrGroupVo = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
skuItemVo.setGroupAttrs(spuItemBaseAttrGroupVo);
}, executor);
/**
* 与前面的获取无关 再开启一个异步任务 无需返回值runAsync
*/
CompletableFuture<Void> imagFuture = CompletableFuture.runAsync(() -> {
//2 sku图片信息
List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId);
skuItemVo.setImages(images);
}, executor);
/**
* 等到所有任务都完成
*/
CompletableFuture.allOf(infoEntityCompletableFuture,attrFuture,descFuture,groupFuture,imagFuture).get();
return skuItemVo;
}
}