CountDownLatch 计算器(具有回调功能)

本文深入讲解了CountDownLatch在Java并发编程中的应用,包括其初始化、await和countDown方法的使用,以及如何通过CountDownLatch实现线程间的同步和等待。文章还介绍了CountDownLatch的常见应用场景,如回调功能的实现。
final CountDownLatch cdl = new CountDownLatch(1);
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    cdl.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        cdl.await(10, TimeUnit.SECONDS);

思路:

CountDownLatch 通过 await 方法 阻塞线程,countDown方法每执行一次 CountDownLatch 值减1,直到 CountDownLatch 值为0,阻塞线程被唤醒。通过CountDownLatch这种 特性 来完成一些回调的功能。

@初始化默认赋值 1

@CountDownLatch 通过 await 方法 永久阻塞线程,直到值为0,会 通过 带时间时效性的阻塞线程,即当时间时效性内 ,线程阻塞,时间到期,阻塞线程 自动唤醒。这个类似于列队带时间参数的插入和出列那2个方法。

@上图中 在10s被被阻塞,10s内 只要CountDownLatch值为0,被阻塞的线程立即 唤醒,开始继续向下执行,否则只能继续阻塞,直到10s到期后阻塞线程也被自动唤醒。

转载于:https://www.cnblogs.com/wzhanke/p/4763961.html

package com.chinamobile.ehr.file.excel.service.error; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.extra.spring.SpringUtil; import com.ai.aif.log4x.Logger; import com.ai.aif.log4x.LoggerFactory; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet; import com.chinamobile.ehr.file.excel.dao.TaskRepository; import com.chinamobile.ehr.file.excel.dto.ExcelResult; import com.chinamobile.ehr.file.excel.dto.RowData; import com.chinamobile.ehr.file.excel.dto.ValidateMsg; import com.chinamobile.ehr.file.excel.utils.EasyExcelUtil; import org.apache.poi.ss.usermodel.*; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; public class EasyExcelErrorThread implements Runnable { private static Logger logger = LoggerFactory.getLogger(EasyExcelErrorThread.class); private BlockingQueue<List<RowData>> validateBlockingQueue; private AtomicBoolean stop = new AtomicBoolean(false); private CountDownLatch countDownLatch = new CountDownLatch(1); private ExcelResult excelResult; private Function<ExcelResult, Boolean> callback; public Function<ExcelResult, Boolean> getCallback() { return callback; } public void setCallback(Function<ExcelResult, Boolean> callback) { this.callback = callback; } public void stopAwait() { try { validateBlockingQueue.put(new ArrayList<>()); countDownLatch.await(5, TimeUnit.MINUTES); } catch (InterruptedException e) { logger.error("错误信息", e); } } public EasyExcelErrorThread(BlockingQueue<List<RowData>> validateBlockingQueue, ExcelResult excelResult) { this.validateBlockingQueue = validateBlockingQueue; this.excelResult = excelResult; } @Override public void run() { Long startTime = System.currentTimeMillis(); ExcelWriter excelWriter = null; InputStream inputStream = null; StringBuilder fileIsExitSB = new StringBuilder(); fileIsExitSB.append("oriFile: ").append(excelResult.getFilePath()); fileIsExitSB.append("errFile:").append(excelResult.getErrorFilePath()).append("; "); try { // 追踪文件是否存在 fileLog(fileIsExitSB,"start"); FileUtil.copy(excelResult.getFilePath(), excelResult.getErrorFilePath(), true); fileLog(fileIsExitSB,"copy"); logger.info("错误导出-复制错误文件:{}",System.currentTimeMillis()-startTime); byte[] errorTemplateBytes = EasyExcelUtil.createErrorTemplate(excelResult.getErrorFilePath(),excelResult.getTableName()); fileLog(fileIsExitSB,"createErrorTemplate"); logger.info("错误导出-生成错误模版:{}",System.currentTimeMillis()-startTime); inputStream = new ByteArrayInputStream(errorTemplateBytes); excelWriter = EasyExcel.write(excelResult.getErrorFilePath()).withTemplate(inputStream).inMemory(Boolean.FALSE).build(); fileLog(fileIsExitSB,"write"); // 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了 WriteSheet writeSheet = EasyExcel.writerSheet(0).needHead(Boolean.FALSE).build(); while (true) { List<RowData> validateRowList = validateBlockingQueue.take(); if (CollectionUtil.isEmpty(validateRowList)) { break; } List<Map<String, Object>> rowList = EasyExcelUtil.getErrorExcelRowList(validateRowList); excelWriter.fill(rowList, writeSheet); // 记录导出数据量,并回调 excelResult.setErrorExportCount(excelResult.getErrorExportCount() + rowList.size()); callback.apply(excelResult); logger.info("错误导出-导出数据-{}:{}",excelResult.getErrorExportCount(),System.currentTimeMillis()-startTime); } //强制计算所有公式(可选) Workbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook(); workbook.setForceFormulaRecalculation(true); // 简单刷新批注 Sheet sheet = workbook.getSheetAt(0); for (Row row : sheet) { for (Cell cell : row) { if (cell.getCellType() == CellType.FORMULA && cell.getCellComment() != null) { cell.setCellComment(cell.getCellComment()); // 重新设置触发刷新 } } } fileLog(fileIsExitSB,"end"); } catch (InterruptedException e) { logger.error("错误导出-写入错误excel错误", e); throw new RuntimeException(e); } finally { // 更新追踪文件是否存在记录 fileLog(fileIsExitSB,"finally"); excelResult.setFileIsExitStr(fileIsExitSB.toString()); callback.apply(excelResult); IoUtil.close(inputStream); IoUtil.close(excelWriter); // 更新错误文件大小 updateFileSize(); countDownLatch.countDown(); logger.info("错误导出-结束:{}", System.currentTimeMillis() - startTime); } } public boolean updateFileSize() { Long size = FileUtil.file(excelResult.getErrorFilePath()).length()/1024; String guid = excelResult.getErrAttachFile(); TaskRepository taskRepository = SpringUtil.getBean(TaskRepository.class); Boolean result = taskRepository.updateFileSize(size, guid); return result; } private void fileLog(StringBuilder fileIsExitSB, String tip){ fileIsExitSB.append(tip).append(": "); boolean oriFileIsExit = FileUtil.isExistsAndNotDirectory(FileUtil.file(excelResult.getFilePath()).toPath(), false); boolean errFileIsExit = FileUtil.isExistsAndNotDirectory(FileUtil.file(excelResult.getErrorFilePath()).toPath(), false); fileIsExitSB.append("oriFileIsExit: ").append(oriFileIsExit).append("; "); fileIsExitSB.append("errFileIsExit: ").append(errFileIsExit).append("; ");; } } 导出的文件有一列是公式列,导出后批注不显示,如何刷新所有批注
最新发布
07-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值