之前总是写串行程序,所以19年的时候写的八字命理程序执行速度很慢,22年开始重构,应用CompletableFuture
就速度飞快了。重构是一种乐趣
同时执行各自维度的分析,最后再统一汇总结果
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@Resource(name = "zpExecutor")
private Executor executor;
private ZpPracticeDto getZpPracticeDto(BaZi baZi,SexEnum sex){
CompletableFuture<List<AssertionDto>> guanluFuture = CompletableFuture.supplyAsync(()->
guanLuService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> pengyouFuture = CompletableFuture.supplyAsync(()->
pengyouService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> hunyinFuture = CompletableFuture.supplyAsync(()->
hunyinService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> jieFuture = CompletableFuture.supplyAsync(()->
jieService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> fudeFuture = CompletableFuture.supplyAsync(()->
fudeService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> zinvFuture = CompletableFuture.supplyAsync(()->
zinvService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> fumuFuture = CompletableFuture.supplyAsync(()->
fumuService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> xinggeFuture = CompletableFuture.supplyAsync(()->
xingGeService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> caiboFuture = CompletableFuture.supplyAsync(()->
caiboService.handle(baZi, sex),executor);
CompletableFuture<List<AssertionDto>> xiongdiFuture = CompletableFuture.supplyAsync(()->
xiongdiService.handle(baZi, sex),executor);
// 数据加载完成
CompletableFuture.allOf(guanluFuture,pengyouFuture,hunyinFuture,jieFuture,fudeFuture,zinvFuture
,fumuFuture,xinggeFuture,caiboFuture,xiongdiFuture).join();
//
ZpPracticeDto zpPracticeDto = new ZpPracticeDto();
zpPracticeDto.setBazi(baZi.toString());
zpPracticeDto.setGuanlus(guanluFuture.join());
zpPracticeDto.setPengyous(pengyouFuture.join());
zpPracticeDto.setHunyins(hunyinFuture.join());
zpPracticeDto.setJies(jieFuture.join());
zpPracticeDto.setFudes(fudeFuture.join());
zpPracticeDto.setZinvs(zinvFuture.join());
zpPracticeDto.setFumus(fumuFuture.join());
zpPracticeDto.setXingges(xinggeFuture.join());
zpPracticeDto.setCaibos(caiboFuture.join());
zpPracticeDto.setXiongdis(xiongdiFuture.join());
return zpPracticeDto;
}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@EnableAsync
@Configuration
@RefreshScope
public class ThreadPoolExecutorConfig {
@Value("${async.executor.thread.core_pool_size}")
private int corePoolSize;
@Value("${async.executor.thread.max_pool_size}")
private int maxPoolSize;
@Value("${async.executor.thread.queue_capacity}")
private int queueCapacity;
@Value("${async.executor.thread.name.prefix}")
private String namePrefix;
@Bean("zpExecutor")
public Executor zpExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(corePoolSize);
//配置最大线程数
executor.setMaxPoolSize(maxPoolSize);
//配置队列大小
executor.setQueueCapacity(queueCapacity);
//配置线程池中线程的名称前缀
executor.setThreadNamePrefix(namePrefix);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
相关的配置如下
#配置核心线程数
async:
executor:
thread:
core_pool_size: 5
max_pool_size: 5
queue_capacity: 10000
name:
prefix: qq-async-
我写的只是应用层,阿里面试:页面调10 个上游接口,如何做高并发?,理论方面可以参考这个。其实从逻辑上去分析并不难,只是很少有人具备这样的推理能力,或者即使有这种推理能力,但总结成立理论需要实践。
重构一下,分析60甲子的数据
long dd = System.currentTimeMillis();
CompletableFuture[] futures = Arrays.stream(LiuShiJiaZiEnum.values()).map(jiazi->
CompletableFuture.supplyAsync(()->{
long startTime = System.currentTimeMillis();
log.info("{}:开始执行",jiazi.display());
BaziInfoCondDto condDto = new BaziInfoCondDto();
condDto.setDay(jiazi.display());
List<BaziInfo> baziInfos = baziInfoService.select(condDto);
List<BaziInfoMogo> baziInfoMogos = new ArrayList<>();
for (BaziInfo baziInfo: baziInfos){
BaziInfoMogo baziInfoMogo = baziInfoMogoService.convert(baziInfo);
//
baziInfoMogos.add(baziInfoMogo);
}
baziInfoMogoRepository.saveAll(baziInfoMogos);
log.info("执行{}:{}ms" ,jiazi.display(),(System.currentTimeMillis() - startTime) );
return String.format("任务%:执行完成",jiazi.display());
},taskExecutor).handle((result,throwable)->{
return result;
}).whenComplete((r,ex)->{
log.info("任务全都执行完成");
})
).toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();
log.info("总执行{}ms" ,(System.currentTimeMillis() - dd) );