需求分析
公司有自己的疾病库,数据量也不是很多有几万条吧,公司想要导出来到EXCLE中进行分析,让我来负责这个事情,记录一下导出过程,优化方案、
伪代码分析
1、查询数据
2、数据组装
3、调用EXCLE工具类
4、导出excle
其实过程非常简单,查询->导出,但是我这几万条数据也等了一会才完成了数据导出那么有没有优化的办法呢?
伪代码优化
我们是不是可以使用多线程呢?
1、多线程查询数据
2、数据组件
3、数据排序
4、数据导出
可以将数据查询进行分片,采用多线程的方式进行查询,比如CountDownLatch就非常契合这个需求,通过数据总数,计算分页总数,创建CountDownLatch,当所有查询线程完成后执行数据排序,然后导出。那么百万级的数据量也同理。
示例代码
可以参考下面的示例代码
public void threadListAll(HttpServletResponse response) throws InterruptedException, IOException {
long start = System.currentTimeMillis();
CountDownLatch countDownLatch = new CountDownLatch(5);
List<Map<String,Object>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
int finalI = i;
new Thread(()->{
Map<String,Object> map = new HashMap<>();
map.put("start", finalI * 500);
map.put("limit", 500);
Integer total = icdDao.icdDetailPageCount(map);
List<IcdDetailItem> segmentList = new ArrayList<>();
if (total > 0) {
segmentList = icdDao.pageList(map);
for (IcdDetailItem icdDetailItem : segmentList) {
Map<String,Object> params = MapUtil.newHashMap(true);
String code = icdDetailItem.getCode();
String[] split = code.split("\\.");
IcdItem icdItem = icdDao.queryByCode(split[0]);
if(icdItem!=null){
params.put("id",icdDetailItem.getId());
params.put("code",icdDetailItem.getCode());
params.put("disease",icdDetailItem.getDisease());
params.put("boyd",icdItem.getBody());
params.put("sysName",icdItem.getSysName());
params.put("sysCode",icdItem.getSysCode());
list.add(params);
}
}
}
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
list.sort((o1, o2) -> (o2.get("id").toString()).compareTo(o1.get("id").toString()));
String tempPath = "D:\\tmp\\icd.xlsx";
File file = new File(tempPath);
BigExcelWriter writer = ExcelUtil.getBigWriter(file);
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(list, true);
//response为HttpServletResponse对象
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
ServletOutputStream out = response.getOutputStream();
// 终止后删除临时文件
// file.deleteOnExit();
writer.flush(out, true);
long end = System.currentTimeMillis();
System.out.println("接口运行时间:"+(end-start));
//此处记得关闭输出Servlet流
IoUtil.close(out);
}