cpu java poi 导出_Java里当POI导出Excel数据比较大时的优化方案

当使用Java POI导出大量数据到Excel时,会出现内存溢出和CPU飙升问题。通过切换到SXSSFWorkbook类,可以将部分数据写入硬盘,降低内存占用。设置合适的rowAccessWindowSize参数,结合压缩临时文件,有效缓解性能瓶颈。
摘要由CSDN通过智能技术生成

问题

在Java里绝大多数都是使用POI进行导入导出Excel,正常情况下也都没有问题。但当导出的数据量比较大时,我留意到我本机当数据量达到两三万条(二十个列)时,就会出现内存溢出,CPU飙升到95%以上的情况。

可能换到好点的服务器上会好点,但情况并不会好太多,还是会存在瓶颈。

解决

使用 SXSSFWorkbook 类代替原来的 XSSFWorkbook 类,SXSSFWorkbook 是3.8以上的POI才开始支持。SXSSFWorkbook 相对于 XSSFWorkbook 进行了一些优化,SXSSFWorkbook是streaming 版本的XSSFWorkbook,它只会保存最新的excel rows在内存里供查看,在此之前的excel rows都会被写入到硬盘里(Windows电脑是写入到C盘根目录下的temp文件夹)。被写入到硬盘里的rows是不可见的/不可访问的。只有还保存在内存里的才可以被访问到。在数据量超过设定的值时,它会用硬盘空间来大幅降低堆内存的占用,在系统的临时文件夹目录创建一个临时文件,然后将所有大于预设行数的数据都存入临时文件,这样就降低了内存的压力,从而实现以硬盘空间换取内存空间,避免内存溢出和频繁GC导致的CPU飙升。

注:HSSFWorkbook和XSSFWorkbook的Excel Sheet导出条数上限(<=2003版)是65535行、256列,(>=2007版)是1048576行,16384列。

使用

引入pom,需要注意的是4.0.0版本的JDK需要1.8以上,如果JDK是1.7的,那么就使用3.8或者3.9版本的依赖。

org.apache.poi

poi-ooxml-schemas

4.0.0

org.apache.poi

poi-ooxml

4.0.0

org.apache.poi

poi

4.0.0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

org.apache.poi

poi-ooxml-schemas

4.0.0

org.apache.poi

poi-ooxml

4.0.0

org.apache.poi

poi

4.0.0

我们要注意SXSSFWorkbook构造器有一些参数,其中有一个rowAccessWindowSize,代表指定的内存中缓存记录数,默认为100,它代表能从Sheet窗口看到多少刚才Create了多少Row,超过的就都放到磁盘里了,如果你设置rowAccessWindowSize为1000,那么你只能看到1000条新创建的数据,如果设置为-1,就会看到全部创建的数据。

SXSSFWorkbook workbook = null;

OutputStream outputStream = null;

try {

outputStream = response.getOutputStream();

// 创建工作簿使用的是SXSSFWorkbook

workbook = new SXSSFWorkbook(1000);

// 设置数据压缩

workbook.setCompressTempFiles(true);

Sheet sheet = workbook.createSheet("表名");

Row titleRow = sheet.createRow(0);

Cell cell = titleRow.createCell(0);

cell.setCellValue("内容");

// 将工作簿写入输出流

workbook.write(outputStream);

} catch (Exception e) {

e.printStackTrace();

}finally {

if (workbook != null) {

// 处理掉临时文件

workbook.dispose();

}

if (outputStream != null) {

outputStream.close();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

SXSSFWorkbookworkbook=null;

OutputStreamoutputStream=null;

try{

outputStream=response.getOutputStream();

// 创建工作簿使用的是SXSSFWorkbook

workbook=newSXSSFWorkbook(1000);

// 设置数据压缩

workbook.setCompressTempFiles(true);

Sheetsheet=workbook.createSheet("表名");

RowtitleRow=sheet.createRow(0);

Cellcell=titleRow.createCell(0);

cell.setCellValue("内容");

// 将工作簿写入输出流

workbook.write(outputStream);

}catch(Exceptione){

e.printStackTrace();

}finally{

if(workbook!=null){

// 处理掉临时文件

workbook.dispose();

}

if(outputStream!=null){

outputStream.close();

}

}

浏览量:

874

0

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值