cc 2 ay önce
ebeveyn
işleme
dd039df916

+ 23 - 6
src/main/java/com/qingjian/common/cache/CaseDataCache.java

@@ -17,6 +17,7 @@ import java.time.LocalDateTime;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 /**
  * CaseDataCache 类用于缓存应用程序运行过程中的数据,
@@ -35,7 +36,10 @@ public class CaseDataCache {
      */
     public static final HashMultimap<String, String> PERSON_LIB_NO_MAP = HashMultimap.create();
     public static final Map<String, String> GOVERN_CONFIG = Maps.newConcurrentMap();
-    private static final Object lock = new Object();
+    // 使用 ReentrantReadWriteLock 替代单一的 Object 锁
+    private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
+    private static final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
+    private static final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
 
     public static void initCache() {
         PERSON_LIB_NO_MAP.clear();
@@ -56,19 +60,28 @@ public class CaseDataCache {
      * 新增人员库
      */
     public static void putPerLib(String key, String value, String bankName) {
-        synchronized (lock) {
+        // 获取写锁
+        writeLock.lock();
+        try {
             PERSON_LIB_NO_MAP.put(key, value);
             String[] keys = StrUtil.splitToArray(key, StrPool.UNDERLINE);
             CleanCache.addPersonLibNo(new PersonLibNo(keys[0], value, Integer.parseInt(keys[1]), 1, bankName));
+        } finally {
+            // 必须在 finally 块中释放锁,确保即使发生异常也能正确释放
+            writeLock.unlock();
         }
 
     }
 
     public static synchronized void putPerLib(String key, String value, LocalDateTime startTime, LocalDateTime endTime, String operatorId) {
-        synchronized (lock) {
+        // 获取写锁
+        writeLock.lock();
+        try {
             PERSON_LIB_NO_MAP.put(key, value);
             String[] keys = StrUtil.splitToArray(key, StrPool.UNDERLINE);
             CleanCache.addPersonLibNo(new PersonLibNo(keys[0], value, Integer.parseInt(keys[1]), startTime, endTime, operatorId));
+        } finally {
+            writeLock.unlock();
         }
     }
 
@@ -87,8 +100,10 @@ public class CaseDataCache {
     }
 
     public static String findPersonVal(String val) {
-        if (PERSON_LIB_NO_MAP.containsValue(val)) {
-            synchronized (lock) {
+        // 获取读锁
+        readLock.lock();
+        try {
+            if (PERSON_LIB_NO_MAP.containsValue(val)) {
                 for (Map.Entry<String, String> entry : PERSON_LIB_NO_MAP.entries()) {
                     String key = entry.getKey();
                     String value = entry.getValue();
@@ -98,8 +113,10 @@ public class CaseDataCache {
                     }
                 }
             }
+            return null;
+        } finally {
+            readLock.unlock();
         }
-        return null;
     }
 
     public static void cleanCache() {

+ 7 - 7
src/main/java/com/qingjian/common/utils/SlowDownProgress.java

@@ -22,27 +22,27 @@ public class SlowDownProgress {
      */
     public int calculateNextProgress() {
         int currentProgress = stepCount.get();
-        if (currentProgress >= 100) {
-            return 100;
+        if (currentProgress >= 99) {
+            return 99;
         }
 
-        int remaining = 100 - currentProgress;
+        int remaining = 99 - currentProgress;
         int increment;
 
         // --- 核心策略:根据剩余空间动态调整最大步长 ---
 
-        if (remaining > 50) {
+        if (remaining > 30) {
             // 阶段1:前期 (剩余 > 50%) -> 步子大,快速前进
             // 随机增加 5% 到 15%
-            increment = random.nextInt(11) + 3;
+            increment = random.nextInt(8) + 3;
         } else if (remaining > 20) {
             // 阶段2:中期 (剩余 10% - 30%) -> 步子中等
             // 随机增加 2% 到 6%
-            increment = random.nextInt(5) + 2;
+            increment = random.nextInt(4) + 2;
         } else {
             // 阶段3:后期 (剩余 < 10%) -> 步子很小,模拟卡顿
             // 随机增加 1% 到 3% (甚至可能只加1%)
-            increment = random.nextInt(3) + 1;
+            increment = random.nextInt(2) + 1;
         }
 
         // 确保不超过剩余空间,防止溢出

+ 4 - 4
src/main/java/com/qingjian/module/dm/clean/CleanTask.java

@@ -81,11 +81,11 @@ public record CleanTask(FileInfo fileInfo, List<FileInfo> sheetList) {
             StreamingEtlListener streamingEtlListener = new StreamingEtlListener(new LogDirtyDataHandler(), excelTypeEnum, sheetList, extractSheetList);
             // 获取文件类型和编码
             Charset charset = Charset.forName(fileInfo.getCharSet());
-            SimpleReadCacheSelector simpleReadCacheSelector = new SimpleReadCacheSelector();
-            simpleReadCacheSelector.setMaxUseMapCacheSize(50L);
-            simpleReadCacheSelector.setMaxCacheActivateBatchCount(20000);
+            //SimpleReadCacheSelector simpleReadCacheSelector = new SimpleReadCacheSelector();
+            //simpleReadCacheSelector.setMaxUseMapCacheSize(50L);
+            //simpleReadCacheSelector.setMaxCacheActivateBatchCount(20000);
             try (ExcelReader reader = FesodSheet.read(Files.newInputStream(Path.of(fileInfo.getFilePath())), streamingEtlListener)
-                    .readCacheSelector(simpleReadCacheSelector)
+                    .readCacheSelector(new SimpleReadCacheSelector(20L, 500))
                     .password(fileInfo.getPassword()).headRowNumber(0).excelType(excelTypeEnum)
                     .autoTrim(true).charset(charset).registerConverter(new Str2NullConverter())
                     .registerConverter(new DateNumberConverter()).build()) {

+ 3 - 5
src/main/java/com/qingjian/module/dm/service/DmService.java

@@ -269,10 +269,8 @@ public class DmService {
 
     private TaskCompleteCallback createDefaultCallback(SlowDownProgress slowDownProgress, Long batchId) {
         return (totalTaskCount, completedTaskCount, message) -> {
-            if (completedTaskCount % 10 == 0 || completedTaskCount == totalTaskCount) {
-                log.info("任务进度:已完成{} / {}({}%)",
-                        completedTaskCount, totalTaskCount, Math.round((double) completedTaskCount / totalTaskCount * 100));
-            }
+            log.info("任务进度:已完成{} / {}({}%)",
+                    completedTaskCount, totalTaskCount, Math.round((double) completedTaskCount / totalTaskCount * 100));
             sseService.sendSee(new SseDTO(101, slowDownProgress.calculateNextProgress(), message, new SeeDataDTO(0, 0)));
             if (completedTaskCount == totalTaskCount) {
                 GlobalCache.initCache();
@@ -375,7 +373,7 @@ public class DmService {
         boolean acquired = false;
         int taskStatus = 0;
         try {
-            acquired = semaphore.tryAcquire(15, TimeUnit.MINUTES);
+            acquired = semaphore.tryAcquire(1, TimeUnit.HOURS);
             if (!acquired) {
                 log.info("任务等待执行许可超时 (系统过载),跳过文件:{}", fileInfo.getFilePath());
                 return;