将三个list往一个excel表的三个sheet中写入,能用多线程提高写入速度

news/2024/12/28 8:55:59/

1. 多线程大批量写入可能导致 OOM

多线程可以加速写入操作,因为每个线程可以独立处理一个 Sheet。
但多线程会导致内存占用增加,因为多个线程可能同时将数据加载到内存中。
如果每个 List 数据量过大,而 JVM 的堆内存不够,就会触发 OOM。

2. 解决 OOM 问题的策略

为了保证程序稳定性并避免 OOM,采取以下措施:

1,使用分批处理数据:将大的 List 分批写入,避免一次性加载所有数据到内存中。
2,使用 SXSSFWorkbook 流式写入:它是 Apache POI 提供的专门用于大数据量 Excel 操作的类。
3,合理设置 JVM 堆内存:通过 JVM 参数如 -Xmx2G 提高堆内存限制。
4,多线程写入:每个线程负责一个 Sheet,实现并发写入加速。

3. 代码示例

假设有三个大 List,我们分别写入 Excel 的三个 Sheet:

依赖引入

使用 Apache POI,需要添加以下依赖(Maven):

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version>
</dependency>
代码实现
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;public class MultiThreadExcelWriter {// 方法:分批写入数据到 Sheetprivate static void writeDataToSheet(Sheet sheet, List<String> data, int batchSize) {int rowIndex = 0;for (int i = 0; i < data.size(); i += batchSize) {List<String> batch = data.subList(i, Math.min(i + batchSize, data.size()));for (String item : batch) {Row row = sheet.createRow(rowIndex++);Cell cell = row.createCell(0);cell.setCellValue(item);}}}public static void main(String[] args) {// 假设有三个大 Listfinal List<String> list1 = generateLargeList(1000000); // 模拟100万条数据final List<String> list2 = generateLargeList(1000000);final List<String> list3 = generateLargeList(1000000);// 创建线程池,控制并发线程数ExecutorService executor = Executors.newFixedThreadPool(3);// 使用 SXSSFWorkbook 实现流式写入Workbook workbook = new SXSSFWorkbook();// 定义任务List<Callable<Void>> tasks = new ArrayList<>();tasks.add(() -> {Sheet sheet1 = workbook.createSheet("Sheet1");writeDataToSheet(sheet1, list1, 10000); // 分批写入,每批1万条return null;});tasks.add(() -> {Sheet sheet2 = workbook.createSheet("Sheet2");writeDataToSheet(sheet2, list2, 10000);return null;});tasks.add(() -> {Sheet sheet3 = workbook.createSheet("Sheet3");writeDataToSheet(sheet3, list3, 10000);return null;});try {// 执行任务executor.invokeAll(tasks);// 将数据写入 Excel 文件try (FileOutputStream fos = new FileOutputStream("output.xlsx")) {workbook.write(fos);}System.out.println("Excel 文件写入完成!");} catch (InterruptedException | IOException e) {e.printStackTrace();} finally {// 关闭线程池和资源executor.shutdown();try {workbook.close();} catch (IOException e) {e.printStackTrace();}}}// 模拟生成大数据 Listprivate static List<String> generateLargeList(int size) {List<String> list = new ArrayList<>(size);for (int i = 0; i < size; i++) {list.add("Data-" + i);}return list;}
}

4. 代码说明

多线程处理:
使用 ExecutorService 创建固定大小的线程池(3个线程)。
每个线程负责一个 Sheet,并将数据分批写入。
分批写入:
writeDataToSheet 方法中,通过 subList 将数据分成小批次(例如每批 10,000 条)写入。
这样可以避免一次性加载过多数据到内存。
流式写入:
使用 SXSSFWorkbook 代替传统的 XSSFWorkbook,它支持流式写入并限制内存占用。
堆内存设置:
在运行程序时,通过 JVM 参数增加堆内存:

java -Xmx2G -jar yourprogram.jar

这里 -Xmx2G 表示将最大堆内存设置为 2GB

5. 执行结果

Excel 文件生成速度更快,因为三个线程并发写入三个 Sheet。
内存占用更可控,通过分批写入和流式写入避免一次性加载过多数据。
Sheet 顺序:
多线程写入不会改变 Sheet 的顺序,因为 SXSSFWorkbook.createSheet 是线程安全的,并且会按照代码中调用顺序创建 Sheet。


http://www.ppmy.cn/news/1557909.html

相关文章

DALL-M:基于大语言模型的上下文感知临床数据增强方法 ,补充

DALL-M&#xff1a;基于大语言模型的上下文感知临床数据增强方法 &#xff0c;补充 论文大纲理解结构分析数据分析1. 数据收集2. 数据处理和规律挖掘3. 相关性分析4. 数学模型建立解法拆解1. 逻辑关系拆解子解法拆解&#xff1a; 2. 逻辑链分析3. 隐性方法分析4. 隐性特征分析5…

软件测试丨性能测试工具-JMeter

JMeter的基本功能概述 JMeter是一个开源的性能测试工具&#xff0c;它带有图形用户界面&#xff08;GUI&#xff09;&#xff0c;专为负载测试和性能测试而设计。我们可以利用它来模拟多个用户同时访问应用程序&#xff0c;以判断其在不同负载下的表现。更令人兴奋的是&#x…

机器学习中数据预处理的方法

数据预处理是机器学习项目中至关重要的一步&#xff0c;它直接影响模型的性能和准确性。 一、数据清洗 数据清洗是数据预处理的首要步骤&#xff0c;主要目的是处理数据中的缺失值、异常值和重复数据等。 1.处理缺失值&#xff1a; 删除含有缺失值的行或列。 均值填充&#…

webserver log日志系统的实现

参考博客&#xff1a;https://blog.csdn.net/weixin_51322383/article/details/130474753 https://zhuanlan.zhihu.com/p/721880618 阻塞队列blockqueue 1、阻塞队列的设计流程是什么样的 它的底层是用deque进行管理的 阻塞队列主要是围绕着生产者消费者模式进行多线程的同步和…

springboot 配置Kafka 关闭自启动连接

这里写自定义目录标题 springboot 配置Kafka 关闭自启动连接方法一&#xff1a;使用 ConditionalOnProperty方法二&#xff1a;手动管理Kafka监听器容器方法三&#xff1a;使用 autoStartupfalse结语 springboot 配置Kafka 关闭自启动连接 在Spring Boot应用程序中&#xff0c…

新版国标GB28181设备端Android版EasyGBD支持国标GB28181-2022,支持语音对讲,支持位置上报,开源在Github

经过近3个月的迭代开发&#xff0c;新版本的国标GB28181设备端EasyGBD安卓Android版终于在昨天发布到Github了&#xff0c;最新的EasyGBD支持了国标GB28181-2022版&#xff0c;还支持了语音对讲、位置上报、本地录像等功能&#xff0c;比原有GB28181-2016版的EasyGBD更加高效、…

用Python设置Excel工作表的页眉和页脚

在处理和分析数据时&#xff0c;Excel作为一款功能强大的工具&#xff0c;被广泛应用于各个领域。当涉及到打印或分享工作表时&#xff0c;为文档添加专业的页眉和页脚不仅能提升文件的视觉效果&#xff0c;还能提供必要的信息&#xff0c;例如公司标识、日期、文件名或是页码等…

微信小程序的轮播图学习报告

微信小程序轮播图学习报告 好久都没分享新内容了&#xff0c;实在惭愧惭愧。今天给大家做一个小程序轮播图的学习报告。 先给大家看一下我的项目状态&#xff1a; 很空昂&#xff01;像一个正在修行的老道&#xff0c;空的什么也没有。 但是我写了 4 个 view 容器&#xff0c;…