多线程解决大数据批量导出问题(demo)

1.首先从网上找一个到工具类,我这里是ExcelUtils,如下

 

package com.org.util;

import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

public class ExcelUtils {
  // 导出 Excel
    public static Integer exportExcel(SXSSFSheet sheet, List<Object> dataList, Integer currentRow) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
        if (null == dataList || dataList.size() == 0) {
            return -1;
        }

        // 反射
        Object object =  dataList.get(0);
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();

        //如果是第一行,创建表头
        if (0 == currentRow) {
            SXSSFRow row = sheet.createRow(currentRow++);
            for (int i = 0; i < fields.length; i++) {
                SXSSFCell cell = row.createCell(i);
                cell.setCellValue(fields[i].getName());//设置单元格的值为字段名
            }
        }
        //填充数据
        for (Object item : dataList) {
            SXSSFRow row = sheet.createRow(currentRow++);
            for (int i = 0; i < fields.length; i++) {
                SXSSFCell cell = row.createCell(i);
                // get Method
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(fields[i].getName(), item.getClass());
                Method getMethod = propertyDescriptor.getReadMethod();
                // value
                Object value = getMethod.invoke(item);
                cell.setCellValue(value.toString());//设置单元格的值为字段值的字符表现形式
            }
        }
        return currentRow;
    }
}

public class DataBaseTest {

    private static final ConcurrentHashMap<Integer, FutureTask<Integer>> taskList = new ConcurrentHashMap<>();

    public static void main(String[] args) throws ExecutionException, InterruptedException, IOException {
        // mapper
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 查出总数
        int totalNum = userMapper.getTotalNum();
        // 10个线程数
        int taskNum = 10;
        // 总数据量
        int avg = (int) Math.floor(totalNum / taskNum);
        int[] startRows = calcStartRowIndex(totalNum, taskNum);
        // Excel
        SXSSFWorkbook workbook = new SXSSFWorkbook();
        SXSSFSheet sheet = workbook.createSheet();

        for (int i = 0; i < taskNum; i++) {
            final int temp = i;
            FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    System.out.println("开始执行任务" + temp + "...");
                    HashMap<String, Object> map = new HashMap<>();
                    List<User> userList = null;
                    // 分页查询
                    if (temp == taskNum - 1) {
                        // 如果是最后一个线程
                        map.put("startIndex", startRows[temp] - 1); //9001-1
                        // 计算起始位置到最后的数量
                        map.put("num", totalNum - startRows[temp] + 1); //10001-9001+1
                        userList = userMapper.getListByPage(map);
                    } else {
                        //如果是前九个线程的花执行下面的操作
                        map.put("startIndex", startRows[temp] == 0 ? 0 : startRows[temp] - 1);
                        map.put("num", avg);
                        userList = userMapper.getListByPage(map);
                    }
                    List<Object> dataList = new ArrayList<>();
                    for (User user : userList) {
                        dataList.add(user);
                    }
                    Integer currentRow = ExcelUtils.exportExcel(sheet, dataList, startRows[temp]);
                    System.out.println("任务" + temp + "执行结束...");
                    return currentRow;
                }
            });
            taskList.putIfAbsent(i, futureTask);
        }

        int taskIndex = 0;
        while (true) {
            FutureTask<Integer> futureTask = taskList.remove(taskIndex++);
            if (null != futureTask) {
                futureTask.run();
                Integer currentRow = futureTask.get();
            }
            if (taskList.size() == 0) {
                // 写入磁盘
                System.out.println("开始写入磁盘");
                FileOutputStream fileOutputStream = new FileOutputStream(new File("c:\\users\\che\\desktop\\test01.xlsx"));
                workbook.write(fileOutputStream);
                break;
            }
        }
    }

    // 计算每一趟起始位置
    public static int[] calcStartRowIndex(int totalNum, int taskNum) {

        int[] resultArray = new int[taskNum];
        int avg = (int) Math.floor(totalNum / taskNum);
        for (int i = 0; i < taskNum; i++) {
            if (i == 0) {
                resultArray[i] = i * avg;
            } else {
                resultArray[i] = i * avg + 1;
            }
        }
        return resultArray;
    }

    public static void addDataSource() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        try {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            for (int i = 0; i < 10000; i++) {
                User user = new User("T" + i, i, "男", "10086", "qwe@qq.com", "日本京都");
                System.out.println(user);
                userMapper.addUser(user);
            }
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            sqlSession.close();
        }
    }
}

具体代码示例包在次处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值