多线程与异步 - raymond-zhao/cat-mall GitHub Wiki

用过线程池吗?系统中是如何使用的?

推荐阅读: 进程、线程与线程池

1. 创建配置属性映射Bean

/**
 * @AUTHOR: raymond
 * @DATETIME: 2020/5/20  17:07
 * DESCRIPTION: 线程池核心配置属性
 **/
@Data
@Component
@ConfigurationProperties(prefix = "mall.threads")
public class ThreadPoolConfigProperties {
	// 核心线程池数量
    private Integer corePoolSize;
	// 最大线程池数量
    private Integer maxPoolSize;
	// 存活等待时间
    private Integer keepAliveTime;

}

2. 新建线程池配置类Bean

/**
 * @AUTHOR: raymond
 * @DATETIME: 2020/5/20  16:53
 * DESCRIPTION: 线程池配置类
 * 因为 ThreadPoolConfigProperties 已经加了 @Component 成为 IoC 容器中的组件
 * 所以可以直接使用
 **/
@Configuration
public class MyThreadConfig {

    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties poolConfigProperties) {
        return new ThreadPoolExecutor(poolConfigProperties.getCorePoolSize(),
                poolConfigProperties.getMaxPoolSize(), poolConfigProperties.getKeepAliveTime(),
                TimeUnit.SECONDS, new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
    }
}

3. 引入依赖进行自动提示

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

4. 通过 properties 配置

mall.threads.core-pool-size=20
mall.threads.max-pool-size=200
mall.threads.keep-alive-time=10

系统中有用到多线程吗?

推荐阅读:

掘金-Java 8 CompletableFuture 教程

图文解析 CompletableFuture

有用到,位于SkuInfoServiceImpl中,使用的是CompletableFuture,把任务提交给上面手动创建的线程池去运行任务。

在获取 SKUItemVO 时使用,因为其中有些任务相互独立,互不干扰,可以并发运行,而有的任务则需要以前一个为基础。

@Override
public SkuItemVO item(Long skuId) throws ExecutionException, InterruptedException {
    SkuItemVO skuItemVO = new SkuItemVO();

    // sku 基本信息
    CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
        SkuInfoEntity info = getById(skuId);
        skuItemVO.setInfo(info);
        return info;
    }, threadPoolExecutor);

    // spu 的销售属性组合
    CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync(res -> {
        List<SkuItemSaleAttrVO> saleAttrVOS = skuSaleAttrValueService.getSaleAttrsBySpuId(res.getSpuId());
        skuItemVO.setSaleAttr(saleAttrVOS);
    }, threadPoolExecutor);

    // spu 介绍
    CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync(res -> {
        SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
        skuItemVO.setDesp(spuInfoDescEntity);
    }, threadPoolExecutor);

    CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync(res -> {
        // spu 的规格参数信息
        List<SpuItemAttrGroupVO> attrGroupVOS = attrGroupService.getAttrGroupWithAttrsBySpuIdAndCatalogId(res.getSpuId(), res.getCatalogId());
        skuItemVO.setGroupAttrs(attrGroupVOS);
    }, threadPoolExecutor);

    CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
        // sku 图片信息
        List<SkuImagesEntity> images = imagesService.getImagesBySkuId(skuId);
        skuItemVO.setImages(images);
    }, threadPoolExecutor);

    CompletableFuture<Void> seckillFuture = CompletableFuture.runAsync(() -> {
        R skuSeckillInfo = seckillFeign.getSkuSeckillInfo(skuId);
        if (skuSeckillInfo.getCode() == 0) {
            SeckillInfoVO seckillInfoVO = skuSeckillInfo.getData(new TypeReference<SeckillInfoVO>() {
            });
            skuItemVO.setSeckillInfo(seckillInfoVO);
        }
    }, threadPoolExecutor);

    CompletableFuture.allOf(saleAttrFuture, descFuture, baseAttrFuture, imageFuture, seckillFuture).get();
    return skuItemVO;
}
⚠️ **GitHub.com Fallback** ⚠️