导出文件20万 线程池

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 订单数据导出工具类
 * 支持大数据量分批导出到Excel文件,每个sheet页5万条数据
 */
public class OrderExportUtil {
    
    // 每个sheet页的最大数据量
    private static final int SHEET_MAX_SIZE = 50000;
    
    // 线程池核心线程数
    private static final int CORE_POOL_SIZE = 4;
    
    // 线程池最大线程数
    private static final int MAX_POOL_SIZE = 8;
    
    // 线程池队列大小
    private static final int QUEUE_SIZE = 10;
    
    /**
     * 导出订单数据到Excel文件
     * @param orders 订单数据列表
     * @param filePath 导出文件路径
     * @throws InterruptedException 线程中断异常
     * @throws ExecutionException 执行异常
     */
    public static void exportOrders(List<Order> orders, String filePath) 
            throws InterruptedException, ExecutionException, IOException {
        
        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(QUEUE_SIZE),
            new ThreadFactory() {
                private final AtomicInteger threadNumber = new AtomicInteger(1);
                
                @Override
                public Thread newThread(Runnable r) {
                    Thread thread = new Thread(r, "OrderExportThread-" + threadNumber.getAndIncrement());
                    thread.setDaemon(false);
                    return thread;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy()
        );
        
        try {
            // 计算需要的sheet数量
            int totalRecords = orders.size();
            int sheetCount = (int) Math.ceil((double) totalRecords / SHEET_MAX_SIZE);
            
            // 使用线程安全的Excel写入器
            ExcelWriter excelWriter = new ExcelWriter(filePath);
            
            // 提交任务到线程池
            List<Future<Void>> futures = new CopyOnWriteArrayList<>();
            
            for (int i = 0; i < sheetCount; i++) {
                int startIndex = i * SHEET_MAX_SIZE;
                int endIndex = Math.min(startIndex + SHEET_MAX_SIZE, totalRecords);
                List<Order> subList = orders.subList(startIndex, endIndex);
                
                final int sheetIndex = i;
                Future<Void> future = executor.submit(() -> {
                    try {
                        excelWriter.writeSheet("订单数据-" + (sheetIndex + 1), subList, sheetIndex);
                        System.out.println("Sheet页 " + (sheetIndex + 1) + " 写入完成,数据量: " + subList.size());
                        return null;
                    } catch (Exception e) {
                        throw new RuntimeException("写入Sheet页失败: " + e.getMessage(), e);
                    }
                });
                
                futures.add(future);
            }
            
            // 等待所有任务完成
            for (Future<Void> future : futures) {
                future.get();
            }
            
            // 完成Excel文件写入
            excelWriter.finish();
            System.out.println("订单数据导出完成,共导出 " + totalRecords + " 条记录,分 " + sheetCount + " 个Sheet页");
            
        } finally {
            // 关闭线程池
            executor.shutdown();
            try {
                if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
}
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Excel写入器 - 使用SXSSFWorkbook支持大数据量写入
 */
class ExcelWriter {
    private final String filePath;
    private final SXSSFWorkbook workbook;
    private final Lock lock = new ReentrantLock();
    
    public ExcelWriter(String filePath) {
        this.filePath = filePath;
        // 创建SXSSFWorkbook,内存中只保留100行数据,避免OOM
        this.workbook = new SXSSFWorkbook(100);
    }
    
    /**
     * 写入单个Sheet页数据
     * @param sheetName sheet页名称
     * @param orders 订单数据
     * @param sheetIndex sheet页索引
     */
    public void writeSheet(String sheetName, List<Order> orders, int sheetIndex) {
        lock.lock();
        try {
            Sheet sheet = workbook.createSheet(sheetName);
            
            // 创建表头
            createHeader(sheet);
            
            // 写入数据行
            int rowNum = 1;
            for (Order order : orders) {
                Row row = sheet.createRow(rowNum++);
                fillRowData(row, order);
            }
            
            // 自动调整列宽
            for (int i = 0; i < 5; i++) {
                sheet.autoSizeColumn(i);
            }
        } finally {
            lock.unlock();
        }
    }
    
    /**
     * 创建表头
     * @param sheet sheet页
     */
    private void createHeader(Sheet sheet) {
        Row headerRow = sheet.createRow(0);
        
        String[] headers = {"订单ID", "客户名称", "订单金额", "下单时间", "订单状态"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            
            // 设置表头样式
            CellStyle headerStyle = workbook.createCellStyle();
            Font font = workbook.createFont();
            font.setBold(true);
            headerStyle.setFont(font);
            cell.setCellStyle(headerStyle);
        }
    }
    
    /**
     * 填充行数据
     * @param row 行对象
     * @param order 订单对象
     */
    private void fillRowData(Row row, Order order) {
        row.createCell(0).setCellValue(order.getOrderId());
        row.createCell(1).setCellValue(order.getCustomerName());
        row.createCell(2).setCellValue(order.getAmount());
        row.createCell(3).setCellValue(order.getOrderTime());
        row.createCell(4).setCellValue(order.getStatus());
    }
    
    /**
     * 完成Excel文件写入并关闭资源
     * @throws IOException IO异常
     */
    public void finish() throws IOException {
        try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
            workbook.write(outputStream);
        } finally {
            workbook.dispose(); // 清理临时文件
        }
    }
}
/**
 * 订单实体类示例
 */
class Order {
    private Long orderId;
    private String customerName;
    private Double amount;
    private String orderTime;
    private String status;
    
    // 构造函数
    public Order(Long orderId, String customerName, Double amount, String orderTime, String status) {
        this.orderId = orderId;
        this.customerName = customerName;
        this.amount = amount;
        this.orderTime = orderTime;
        this.status = status;
    }
    
    // Getter方法
    public Long getOrderId() { return orderId; }
    public String getCustomerName() { return customerName; }
    public Double getAmount() { return amount; }
    public String getOrderTime() { return orderTime; }
    public String getStatus() { return status; }
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 使用示例
 */
public class OrderExportExample {
    public static void main(String[] args) {
        try {
            // 模拟生成20万订单数据
            List<Order> orders = generateMockOrders(200000);
            
            // 导出订单数据
            long startTime = System.currentTimeMillis();
            OrderExportUtil.exportOrders(orders, "orders_export.xlsx");
            long endTime = System.currentTimeMillis();
            
            System.out.println("导出完成,耗时: " + (endTime - startTime) + "ms");
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 生成模拟订单数据
     * @param count 订单数量
     * @return 订单列表
     */
    private static List<Order> generateMockOrders(int count) {
        List<Order> orders = new ArrayList<>(count);
        String[] statuses = {"已下单", "已付款", "已发货", "已完成", "已取消"};
        Random random = new Random();
        
        for (long i = 1; i <= count; i++) {
            Order order = new Order(
                i,
                "客户" + i,
                100.0 + random.nextDouble() * 9900.0,
                "2023-10-" + String.format("%02d", (i % 30) + 1),
                statuses[random.nextInt(statuses.length)]
            );
            orders.add(order);
        }
        
        return orders;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值