提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
在面试过程中我们经常会被问到多线程的问题。但是在实际工作过程中可能使用的场景不是特别多,在这边给大家提供一个多线程使用的实际场景案例。
一、多线程使用背景
在目前参与的智慧大屏项目中,部分初始数据需要通过 Excel 导入到数据库。最大的一个 Excel 表中有约 100 万条数据,单线程批量插入的时间消耗超过两个小时,这显然不可接受。因此,我们打算通过多线程插入的方式来优化代码。
二、代码实现
1.单线程插入
代码如下:
@Slf4j
public class HouseImportListener extends AnalysisEventListener<HouseImportVo> implements ExcelListener<HouseImportVo> {
private final HouseReportMapper houseReportMapper;
private List<HouseReport> dataList = new ArrayList<>();
public HouseImportListener() {
this.houseReportMapper = SpringUtils.getBean(HouseReportMapper.class);
}
@Override
public void invoke(HouseImportVo houseImportVo, AnalysisContext context) {
try {
HouseReport houseReport=new HouseReport();
houseReport.setContractNumber(houseImportVo.getContractNumber());
houseReport.setLocation(houseImportVo.getLocation());
houseReport.setArea(houseImportVo.getArea());
houseReport.setType(houseImportVo.getType());
houseReport.setBank(houseImportVo.getBank());
dataList.add(houseReport);
} catch (Exception e) {
log.error("数据转换出错:{}",e.getMessage());
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
houseReportMapper.insertBatch(dataList);
}
@Override
public ExcelResult<HouseImportVo> getExcelResult() {
return new ExcelResult<>() {
@Override
public String getAnalysis() {
return "插入数据完成!";
}
@Override
public List<HouseImportVo> getList() {
return null;
}
@Override
public List<String> getErrorList() {
return null;
}
};
}
}
2.多线程插入
代码如下(示例):
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
//大于2000使用多线程插入
int size = dataList.size();
if(size>2000){
//每批插入1000条
int num=1000;
//计算总批次
int batch=(size+num-1)/num;
/*
* 线程池,20代表核心线程数,100代表最大线程数,10代表线程空间时间
*/
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,20,10, TimeUnit.SECONDS,new ArrayBlockingQueue<>(batch));
//分批循环插入
for (int i = 0; i < batch; i++) {
int start=num*i;
int end=Math.min((i+1)*num,size);
List<HouseReport> threadData = dataList.subList(start, end);
Runnable task=()->{
houseReportMapper.insertBatch(threadData);
};
threadPoolExecutor.execute(task);
}
}else {
houseReportMapper.insertBatch(dataList);
}
}
总结
通过将插入方式修改为多线程之后,插入效率显著提供,可以在20分钟内将100W条数据读取并插入到数据库中。
标签:批量,dataList,houseReport,插入,Override,多线程,public From: https://blog.csdn.net/yanting_java/article/details/142905953