• 模板方法中的线程安全问题


    1、线程安全?

    是否存在临界区,共享的变量,会被不同线程写入

    那么模板方法里面基类的成员变量或者方法就会存在线程安全问题

    2、excel 

     

    AbstractExcelSheet

    业务数据和excel 逻辑 解耦

    让data 可以 在service 层之间set进来

    这样excel的相关类不用添加到 spring 容器中

     

    复制代码
    public abstract class AbstractExcelSheet {
        private XSSFWorkbook workbook;
    
        private XSSFSheet sheet;
    
        /**
         * 写入数据
         */
        private List data;
    
        public void setData(List data) {
            this.data = data;
        }
    
        /**
         * 获取当前类的sheet对象
         *
         * @return sheet对象
         */
        public XSSFSheet getSheet() {
            return sheet;
        }
    
        /**
         * 设置sheet对象
         *
         * @param sheet sheet对象
         */
        public void setSheet(XSSFSheet sheet) {
            this.sheet = sheet;
        }
    
        /**
         * 获取所属的excel对象
         *
         * @return excel对象
         */
        public XSSFWorkbook getWorkbook() {
            return workbook;
        }
    
        /**
         * 设置excel对象
         *
         * @param workbook excel对象
         */
        public void setWorkbook(XSSFWorkbook workbook) {
            this.workbook = workbook;
        }
    
        /**
         * 创建sheet页基本信息
         */
        public abstract void createSheet();
    
        /**
         * 在子类重写
         *
         * @return 标题列
         */
        public abstract List getTitles();
    
        /**
         * 生成sheet标题列,此方法不必重写
         */
        public void createTitleRow() {
            List titles = getTitles();
            // 得到行
            XSSFRow titleRow = getSheet().createRow(0);
            for (int i = 0; i < titles.size(); i++) {
                XSSFCell cell = titleRow.createCell(i);
                cell.setCellStyle(ExportExcelUtil.getTitleStyle(getWorkbook()));
                cell.setCellValue(titles.get(i));
            }
            // 设置行高
            titleRow.setHeight((short) 460);
        }
    
        /**
         * 添加导出excel的内容
         *
         * @param data 导出数据
         */
        public abstract void createDataRow(List data);
    
        /**
         * writeSheetData
         */
        public void writeSheetData() {
            // 创建表单 sheet
            createSheet();
            // sheet 设置表头内容(第一行内容)
            createTitleRow();
            // 从数据库取数并写到文件中
            createDataRow(data);
        }
    
        /**
         * 写入一行 sheet 数据
         *
         * @param rowIndex sheet 写入 行索引
         * @param data sheet 实体数据
         * @param enumValues sheet 表头标题
         * @param  泛型
         */
        protected  void writeRowData(int rowIndex, S data, SheetTitleEnum[] enumValues) {
            XSSFRow row = getSheet().createRow(rowIndex);
            int colIndex = 0;
            XSSFCell cell = row.createCell(colIndex);
            for (SheetTitleEnum enumValue : enumValues) {
                String cellValue = ExportExcelUtil.getCellValue(data, enumValue);
                cell.setCellValue(cellValue);
                cell = row.createCell(++colIndex);
            }
        }
    }
    复制代码

    BusiPackageResultExcelSheet

    业务知识包检查结果.xlsx 业务知识包检查结果 sheet

     

    复制代码
    public class BusiPackageResultExcelSheet extends AbstractExcelSheet {
        private final static String SHEET_NAME = "业务知识包检查结果";
    
        @Override
        public void createSheet() {
            this.setSheet(this.getWorkbook().createSheet(SHEET_NAME));
        }
    
        @Override
        public List getTitles() {
            return BusiPackageResultSheetTitleEnum.titles;
        }
    
        @Override
        public void createDataRow(List data) {
            // 表头 rowIndex = 0, 所以 rowIndex = 1
            int rowIndex = 1;
            SheetTitleEnum[] enumValues = BusiPackageResultSheetTitleEnum.values();
            for (T dataEntry : data) {
                // 写入行数据
                writeRowData(rowIndex++, dataEntry, enumValues);
            }
        }
    }
    复制代码

    BusiPkgRuleResultExcelSheet

    业务知识包检查结果.xlsx 规则检查结果 sheet
    复制代码
    public class BusiPkgRuleResultExcelSheet extends RuleResultExcelSheet {
        @Override
        public void createDataRow(List data) {
            // 表头 rowIndex = 0, 所以 rowIndex = 1
            int rowIndex = 1;
            for (T dataEntry : data) {
                // 写入行数据
                writeRowData(rowIndex++, dataEntry, RuleResultSheetTitleEnum.values());
            }
        }
    }
    复制代码

     

    RuleResultExcelSheet

    规则检查结果.xlsx 规则检查结果 sheet
    复制代码
    public class RuleResultExcelSheet extends AbstractExcelSheet {
        private final static String SHEET_NAME = "规则检查结果";
    
        @Override
        public void createSheet() {
            this.setSheet(this.getWorkbook().createSheet(SHEET_NAME));
        }
    
        /**
         * 表头内容
         *
         * @return 表头内容
         */
        @Override
        public List getTitles() {
            return RuleResultSheetTitleEnum.titles;
        }
    
        @Override
        public void createDataRow(List data) {
            // 表头 rowIndex = 0, 所以 rowIndex = 1
            int rowIndex = 1;
            SheetTitleEnum[] enumValues = RuleResultSheetTitleEnum.values();
            for (T dataEntry : data) {
                // 写入行数据
                writeRowData(rowIndex++, dataEntry, enumValues);
            }
        }
    }
    复制代码

    上面的设计 大部分的方法都是在基类实现了

    当excel的表头不一样,是在子类实现的

    3、线程安全问题点

    所有的成员变量都有可能被其他线程争抢,

    比如 线程1 setData data1 

    但是此时如果线程1 excel 还没导出成功,

    线程2进来了 setData data2

    把线程1的 data 覆盖了

    其实还有很多线程问题,因为多线程是不可控的

    4、解决

     service 在的调用 excel 实现类的时候,变成局部变量

    在单应用中 合理运用 synchronized 、ReentrantLock、 ThreadLocal 原子应用

    分布式 合理运用 redis 锁

    两种运用,注意死锁问题

  • 相关阅读:
    RabbitMQ高级知识点
    Android12之H264、H265、H266视频编码标准总结(四十八)
    音视频从入门到精通——FFmpeg结构体:AVFrame分析
    MySQL----C语言连接(简略)
    对doccano自动标注使用的默认UIE模型进行微调以提高特定领域的实体识别能力,提高标注速度
    【Linux】进程控制
    使用AWVS进行漏洞扫描实验,保姆教程
    maya2018 bonus tools - Arnold材质库1489行报错问题解决方法
    【带限制的完全背包】Educational Codeforces Round 133 (Rated for Div. 2) D. Chip Move
    彻头彻尾理解JVM系列之七:对象在分代模型中的流转过程是怎样的?
  • 原文地址:https://www.cnblogs.com/linzm14/p/17373666.html