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

ops/2024/12/23 17:33:45/

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/ops/144344.html

相关文章

Unity 开发Apple Vision Pro物体识别追踪ObjectTracking

当您在 visionOS 应用中实现对象跟踪时&#xff0c;您可以将现实世界中的物体无缝集成到人们的周围环境中&#xff0c;以增强他们的沉浸式体验。通过跟踪一个或多个物体的 3D 位置和方向&#xff0c;您的应用可以使用虚拟内容增强它们。 您可以使用对象跟踪来提供与人周围环境…

# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)

↑ 上方下载文档 (大小374KB) 接口文档预览 (超过50个接口) 一、数据库25张表er-关系清晰构图&#xff01;(tip: 鼠标右键图片 > 放大图像) 二、难点/经验 详细说明 热门评论排序评论点赞列表|DTO封装经验分享|精华接口文档说明 组员都说喜欢分档对应枚举码 如果这篇文章…

从源码层级深入探索 Spring AMQP 如何在 Spring Boot 中实现 RabbitMQ 集成——消费者如何进行消费

本章节主要从底层源码探索Spring Boot中RabbitMQ如何进行消费&#xff0c;至于RabbitMQ是如何使用如何生产消息&#xff0c;本章不做过多介绍&#xff0c;感兴趣的小伙伴可以参考&#xff1a;从源码层级深入探索 Spring AMQP 如何在 Spring Boot 中实现 RabbitMQ 集成——生产者…

探究大模型为何因数据增多而效果更佳及其优势

一、数据增多为何能提升大模型效果 数据是大模型的“粮食”&#xff0c;是其学习与成长的基石。数据量的增加对于大模型效果的提升&#xff0c;主要得益于以下几个方面的因素&#xff1a; 模型训练的充分性&#xff1a; 大模型通常拥有数百万甚至数十亿个参数&#xff0c;这些…

数位dp-acwing(数字游戏)

题目&#xff1a;数字游戏 1082. 数字游戏 - AcWing题库 分析&#xff1a; 前缀和思想: dp(m) - dp(n-1) 用树的角度分析。 比最高位小的&#xff0c; 左分支讨论&#xff0c;等于最高位的进入右分支&#xff0c;&#xff08;同时进入右分支有条件&#xff0c;就是当前位最…

SMMU软件指南SMMU编程之命令队列

安全之安全(security)博客目录导读 SMMU通过内存中的循环命令队列进行控制。例如&#xff0c;当软件更改STE或翻译时&#xff0c;需要在SMMU中失效相关缓存。这可以通过向命令队列发出相应的失效命令来实现。有关命令类型的详细信息&#xff0c;请参见“命令”部分。 在SMMUv3…

游戏关卡分析:荒野大镖客2雪山终战

1、相关剧情 主角约翰一家在农场过着悠闲的日子&#xff0c;突然平静被打破&#xff0c; 女枪手来报信&#xff0c;在某小镇找到了迈卡的消息。 于是激发了约翰的满腔怒气&#xff0c;不顾妻子的反对&#xff0c;坚决要出战&#xff0c; 要彻底歼灭迈卡&#xff0c;为亚瑟…

MVVM、MVC、MVP 的区别

MVVM&#xff08;Model-View-ViewModel&#xff09;、MVC&#xff08;Model-View-Controller&#xff09;和MVP&#xff08;Model-View-Presenter&#xff09;是三种常见的软件架构模式&#xff0c;它们在客户端应用开发中被广泛使用。每种模式都有其特定的设计理念和应用场景&…