问题
实习中存在一处文件导出的问题,原来是同步导出,但运行一段时间后会出现CPU飙高系统报警
解决思路
1.限制导出条数
2.增加判断条件
3.采用异步导出
4.休眠
以导出课程为例:输入课程类别,选修类型就会导出符合查询条件的结果
业务代码展示
@Service
@Slf4j
public class ExportService {
@Resource
private ClassService classService;
@Async("exportAsyncPool")
public void ExportExcel(String classCategory, String classType) {
//增加判断条件
if (StringUtils.isEmpty(classCategory) || StringUtils.isEmpty(classType)) {
throw new RuntimeException("未填写课程类别或修读类型");
}
try {
String fileName="课程导出示例";
ExcelUtils.ExcelVO excelVO = ExcelUtils.buildSheet(fileName, "课程导出", ClassBO.class);
ExcelWriter excelWriter = excelVO.getExcelWriter();
WriteSheet writeSheet = excelVO.getWriteSheet();
File tempFile = excelVO.getTempFile();
int pageIndex = 1;
int pageSize = 20;
int count=0;
do {
log.info("asyncExportExcel in progress,pageIndex={},count={}", pageIndex, count);
//rpc请求
List<ClassDTO> classDTOList = classService.queryClassList(classCategory,classType, pageIndex, pageSize);
if (CollectionUtils.isEmpty(classDTOList)) {
break;
}
// 转化为导出对象
List<ClassBO> exportInfoBOList = convertClassBO(classDTOList);
ExcelUtils.writeData(excelWriter, writeSheet, exportInfoBOList);
pageIndex++;
count += exportInfoBOList.size();
Thread.sleep(50L);
//最多导出10w条
} while (count < 100000);
excelWriter.finish();
log.info("文件写入完成.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private List<ClassBO>convertClassBO(List<ClassDTO>classDTOList){
List<ClassBO>classBOS=new ArrayList<>();
for(ClassDTO classDTO:classDTOList){
ClassBO bo=new ClassBO();
bo.setClassId(classDTO.getClassId());
bo.setClassName(classDTO.getClassName());
bo.setClassType(classDTO.getClassType());
bo.setDescription(classDTO.getDescription());
}
return classBOS;
}
}
@Configuration
public class ThreadConfig {
@Bean
public Executor exportAsyncPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(16);
executor.setMaxPoolSize(16);
executor.setQueueCapacity(64);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("ExportExecutor-");
//直接抛异常
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
executor.initialize();
return executor;
}
}