POI使用多线程导出多sheet页的Excel
一、前言
最近公司有个业务,需要导出多个sheet页的Excel,其中包括一个汇总sheet和8个子sheet,如下图所示。因为每个子sheet数据量可能达到1W以上,随着业务拓展,以后可能sheet会更多,因此这里需要使用多线程操作sheet导出Excel。网上查了很多资料,很多博主说POI不支持多线程操作sheet,但我就是实现了。
本文主要讲述使用多线程进行多个sheet的同时操作,这是宝贵的经验,留给自己以后参详,也留给广大网友做个参考
二、实现方式
由于我的业务功能限制,所以需要先准备好Excel模板,具体实现方式是,先读取excel模板中的sheet,业务中有几个sheet就循环几次,每次循环都复制第一个sheet模板页,然后使用多线程插入数据,最后删除第一个sheet页,比如:我先读取我excel模板的第一个sheet,需要做8个sheet页的导出,就循环8次,每次循环将第一个sheet复制一份出来,一共复制出来8份,最后删除第一个模板页就好了。
二、主体业务
废话不多说了,上代码
// 在类的外部声明一个原子整型变量,用来作为计数器
//提交线程任务使用的lambda表达式,lambda表达式属于内部类
//所以在外部定义int sum = 0;的话,表达式内部无法对sum进行累加
AtomicInteger cylinderNum = new AtomicInteger(0);
//定义一个长度为8的固定长度线程池。
ExecutorService executorService= Executors.newFixedThreadPool(8);
//开启一个countDownLatch计数器,等到各线程执行完成后再执行main线程
CountDownLatch countDownLatch= new CountDownLatch(fillReportBo.getStationIds().size());
for (int i=0; i<8; i++) {
List<FillDataInfoVo> fillInfoList = fillReportMapper.getFillListDataInfo(fillReportBo);
// 记录每次循环中数据的总量,使用原子整型变量的方法进行操作,保证线程安全
cylinderNum.addAndGet(fillInfoList.size());
// 复制一个子sheet工作表
//这里十分重要,复制sheet一定要在发起线程任务之外,也就是一定要在主线程去操作,不能放在子线程里
XSSFSheet sheetData = workbook.cloneSheet(1, "sheet" + (i+1))