通过多线程处理集合里面的大量数据,提高数据导出效率。

前言:前段时间在写表格导出的时候,需要导出的数据集合需要循环处理,但是速度太慢,所以看了一下如何使用多线程加快导出速度,如有不足之处,请多批评指正。

注意:对象类实现Cloneable接口,不然导出会发现数据混乱。

@Data
public class EmployeeException extends BaseObject implements Cloneable {
    /**
    * 异常员工ID
    */
    private String employeeId;

    /**
    * 异常日期
    */
    private Date exceptionDate;

    /**
    * 1.未签到异常 2.未签退异常 3.未提交任务异常 4.未审批任务异常 5.工时异常
    */
    private Integer exceptionType;

    /**
     * 用于模糊搜索
     */
    private String name;
    private String startTime;
    private String endTime;
    private String departmentId;
    private String projectId;
    /**
     * 用于展示详情
     */
    private String signInTime;
    private String signLocation;
    private String signOutTime;
    private String signOutLocation;
    private String projectName;
    private String startTimeForCut;
    private String endTimeForCut;

    /**
     * 新增status字段,用来判断此异常是否已经审批通过异常报备  异常报备的状态:0.未审批 1:审批通过 2:审批驳回
     */
    private Integer status;

    @Override
    public EmployeeException clone() throws CloneNotSupportedException {
        return (EmployeeException)super.clone();
    }

}

1、Controller层方法

public void exportEmployeeException(employeeException) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        InputStream inStream = null;
        OutputStream outputStream = null;
        String isExport = "succ";
        HttpSession session = this.getServletRequest().getSession();
        try {
            employeeExceptionService.exportEmployeeException2(employeeException, os);
            String fileName = URLEncoder.encode(dateFormat.format(new Date()) + "列表");
            os.flush();
            byte[] buf = os.toByteArray();
            log.info("生成excel长度:" + buf.length + "字节");
            inStream = new ByteArrayInputStream(buf);
            this.getServletResponse().reset();
            this.getServletResponse().setContentType("application/vnd.ms-excel");
            this.getServletResponse().setCharacterEncoding("UTF-8");
            this.getServletResponse().addHeader("Content-Disposition",
                    "attachment; filename=\"" + fileName + ".xlsx\"");
            byte[] b = new byte[1024];
            int len;
            outputStream = this.getServletResponse().getOutputStream();
            while ((len = inStream.read(b)) > 0) {
                outputStream.write(b, 0, len);
            }
        } catch (Exception e) {
            log.error("{}", e);
            isExport = "fail";
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (inStream != null) {
                    inStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (Exception e) {
                logger.error("os close exception!!", e);
            }
            session.setAttribute("isExport", isExport);
        }
    }

2、service层方法

注:handleList(employeeException, employeeExceptionList, 5)方法用到了多线程的知识。

public void exportEmployeeException2(EmployeeException employeeException, ByteArrayOutputStream os) throws InterruptedException {
        List<EmployeeException> employeeExceptionList = employeeExceptionMapper.selectAllEmployeeExceptionList(employeeException);
        handleList(employeeException, employeeExceptionList, 5);
        ArrayList<Map<String, String>> data = new ArrayList<>();
        for (EmployeeExceptionExport employeeExceptionExport : employeeExceptionExportList) {
            Map<String, String> map1 = ObjectUtil.objectToMap(employeeExceptionExport, "");
            data.add(map1);
        }
        int[] headWidth = new int[]{15, 15, 15};
        LinkedHashMap<String, String> relation = new LinkedHashMap<>();
        relation.put("员工姓名", "employeeName");
        relation.put("员工性别", "sex");
        relation.put("员工手机号", "phone");
        log.info("导出报表完成");
        BaseExcelExportUtils baseExcelExportUtils = new BaseExcelExportUtils(headWidth) {
            @Override
            public String setCellStyle(Cell cell, String attrStr) {
                return null;
            }
        };
        baseExcelExportUtils.exportInwork(data, os, relation, "异常扣分导出表");
    }

3、handleList(employeeException, employeeExceptionList, 5)方法,employeeExceptionList即为要处理的集合。

public synchronized void handleList(EmployeeException employeeException, List<EmployeeException> data, int threadNum) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        int length = data.size();
        int tl = length % threadNum == 0 ? length / threadNum : (length
                / threadNum + 1);
        long l = System.currentTimeMillis();
        for (int i = 0; i < threadNum; i++) {
            int end = (i + 1) * tl;
            EmployeeException clone = null;
            try {
                clone = employeeException.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            executorService.execute(new HandleThread("线程[" + (i + 1) + "] ", data, i * tl, end > length ? length : end, clone));
        }
        executorService.shutdown();
        while (true) {
            if (executorService.isTerminated()) {
                System.out.println("结束了!");
                long l1 = System.currentTimeMillis();
                long time = l1 - l;
                System.out.println(time);
                break;
            }
            Thread.sleep(200);
        }
    }

    class HandleThread extends Thread {
        private String threadName;
        private List<EmployeeException> data;
        private int start;
        private int end;
        private EmployeeException employeeException;

        public HandleThread(String threadName, List<EmployeeException> data, int start, int end, EmployeeException employeeException) {
            this.threadName = threadName;
            this.data = data;
            this.start = start;
            this.end = end;
            this.employeeException = employeeException;
        }

        public void run() {
            List<EmployeeException> employeeExceptionList = data.subList(start, end);
            for (EmployeeException exception : employeeExceptionList) {
            -------这里面可以对集合中的每一个对象进行处理----------
    }

4、BaseExcelExportUtils导出表格工具类。

@Slf4j
@NoArgsConstructor
public abstract class BaseExcelExportUtils {
    private int[] headWidth;
    private Map<String, CellStyle> styles;

    public BaseExcelExportUtils(int[] headWidth) {
        this.headWidth = headWidth;
    }

    private static Map<String, CellStyle> createStyles(Workbook wb) {
        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
        DataFormat df = wb.createDataFormat();

        CellStyle style;
        Font headerFont = wb.createFont();
        headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
        style = createBorderedStyle(wb);
        style.setAlignment(CellStyle.ALIGN_CENTER);
        style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE
            .getIndex());
        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style.setFont(headerFont);
        style.setDataFormat(df.getFormat("text"));
        styles.put("header", style);

        style = createBorderedStyle(wb);
        style.setAlignment(CellStyle.ALIGN_LEFT);
        style.setWrapText(true);
        style.setDataFormat(df.getFormat("text"));
        style.setLocked(true);
        styles.put("cell_normal", style);

        style = createBorderedStyle(wb);
        style.setAlignment(CellStyle.ALIGN_RIGHT);
        style.setWrapText(true);
        style.setDataFormat(df.getFormat("text"));
        style.setLocked(true);
//		style.setLeftBorderColor((short) 1);
//		style.setBorderLeft((short) 1);
        styles.put("cell_decimal", style);

        style = createBorderedStyle(wb);
        style.setAlignment(CellStyle.ALIGN_LEFT);
        style.setWrapText(true);
        style.setDataFormat(df.getFormat("text"));
        style.setLocked(false);
        styles.put("cell_normal_writable", style);

        style = createBorderedStyle(wb);
        style.setAlignment(CellStyle.ALIGN_RIGHT);
        style.setWrapText(true);
        style.setDataFormat(df.getFormat("text"));
        style.setLocked(false);
        styles.put("cell_decimal_writable", style);

        //有问题的帐号样式
        style = createBorderedStyle(wb);
        style.setAlignment(CellStyle.ALIGN_CENTER);
        style.setFillForegroundColor(IndexedColors.RED
            .getIndex());
        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style.setDataFormat(df.getFormat("text"));
        styles.put("cell_red", style);

        style = createBorderedStyle(wb);
        style.setAlignment(CellStyle.ALIGN_CENTER);
        style.setFillForegroundColor(IndexedColors.YELLOW
            .getIndex());
        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style.setDataFormat(df.getFormat("text"));
        styles.put("cell_yellow", style);

        style = createBorderedStyle(wb);
        style.setAlignment(CellStyle.ALIGN_CENTER);
        style.setFillForegroundColor(IndexedColors.SKY_BLUE
            .getIndex());
        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style.setDataFormat(df.getFormat("text"));
        styles.put("cell_skyblue", style);

        return styles;
    }

    private static CellStyle createBorderedStyle(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        style.setBorderRight(CellStyle.BORDER_THIN);
        style.setRightBorderColor(IndexedColors.BLACK.getIndex());
        style.setBorderBottom(CellStyle.BORDER_THIN);
        style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        style.setBorderLeft(CellStyle.BORDER_THIN);
        style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
        style.setBorderTop(CellStyle.BORDER_THIN);
        style.setTopBorderColor(IndexedColors.BLACK.getIndex());
        return style;
    }

    public abstract String setCellStyle(Cell cell, String attrStr);

    public void exportInwork(List<Map<String, String>> data, ByteArrayOutputStream os, ExcelHeaderRelationship excelHeaderRelationship, String title) {
        try {
            XSSFWorkbook wb = new XSSFWorkbook();//创建excel
            styles = createStyles(wb);//设置样式
            if (data != null && data.size() > 0) {

                //init excle
                Cell cell = null;
                Row row;
                XSSFSheet sheet = wb.createSheet(title);
                // turn off gridlines
                initExcle(sheet);
                //init header
                TreeMap<String, String> relations = excelHeaderRelationship.getRelations();
                List<String> relaList = initHeader(sheet, relations);
                //init body
                for (int i = 1; i <= data.size(); i++) {
                    row = sheet.createRow(i);
                    Map<String, String> rowData = data.get(i - 1);
                    for (int j = 0; j <= relaList.size(); j++) {
                        cell = row.createCell(j);
                        if (j == 0) {
                            //序号
                            cell.setCellValue(i);
                            cell.setCellStyle(styles.get("cell_normal"));
                        } else {
                            String attrStr = relations.get(relaList.get(j - 1));
                            String valStr = rowData.get(attrStr);
                            //set cell style
                            cell.setCellValue(valStr);
                            cell.setCellStyle(styles.get(setCellStyle(cell, attrStr)));
                        }
                    }
                }
                wb.write(os);
            }
        } catch (Exception e) {
            log.error("{}", e);
        }
    }

    public void exportInwork(List<Map<String, String>> data, ByteArrayOutputStream os, Map<String, String> relation, String title) {
        try {
            log.info("创建excel");
            XSSFWorkbook wb = new XSSFWorkbook();//创建excel
            styles = createStyles(wb);//设置样式


            //init excle
            log.info("init excle");
            Cell cell = null;
            Row row;
            XSSFSheet sheet = wb.createSheet(title);
            // turn off gridlines
            initExcle(sheet);
            //init header
            log.info("init header");
            List<String> relaList = initHeader(sheet, relation);
            //init body
            if (data != null && data.size() > 0) {
                log.info("init body");
                for (int i = 1; i <= data.size(); i++) {
                    row = sheet.createRow(i);
                    Map<String, String> rowData = data.get(i - 1);
                    for (int j = 0; j <= relaList.size(); j++) {
                        cell = row.createCell(j);
                        if (j == 0) {
                            //序号
                            cell.setCellValue(i);
                            cell.setCellStyle(styles.get("cell_normal"));
                        } else {
                            String attrStr = relation.get(relaList.get(j - 1));
                            String valStr = String.valueOf(rowData.get(attrStr));
                            //set cell style
                            cell.setCellValue(valStr);
                            cell.setCellStyle(styles.get(setCellStyle(cell, attrStr)));
                        }
                    }
                }
            }
            wb.write(os);
            log.info("完成生成excel");
        } catch (Exception e) {
            log.error("{}", e);
        }
    }

    private void initExcle(XSSFSheet sheet) {
        sheet.setDisplayGridlines(true);
        sheet.setPrintGridlines(true);
        sheet.setFitToPage(true);
        sheet.setHorizontallyCenter(true);
        PrintSetup printSetup = sheet.getPrintSetup();
        printSetup.setLandscape(true);
        // the following three statements are required only for XSSF
        sheet.setAutobreaks(true);
        printSetup.setFitHeight((short) 1);
        printSetup.setFitWidth((short) 1);
    }

    private List<String> initHeader(XSSFSheet sheet, Map<String, String> relations) {
        Row dataRow = sheet.createRow(0);
        Set<String> keys = relations.keySet();
        Set<Map.Entry<String, String>> entries = relations.entrySet();
        Iterator<String> iterator = keys.iterator();
        List<String> relaList = new ArrayList<>();
        int k = 0;
        Cell noCell = dataRow.createCell(k);
        noCell.setCellValue("序号");
        noCell.setCellStyle(styles.get("header"));
        sheet.setColumnWidth(k, 256 * headWidth[k]);
        k++;
        while (iterator.hasNext()) {
            String key = iterator.next();
            relaList.add(key);
            Cell cell = dataRow.createCell(k);
            cell.setCellValue(key);
            cell.setCellStyle(styles.get("header"));
            sheet.setColumnWidth(k, 256 * headWidth[k]);
            k++;
        }
        return relaList;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值