From e47d11017af9eff6581591d5d73c1e55676b0955 Mon Sep 17 00:00:00 2001
From: 啊鑫 <t2856754968@163.com>
Date: 星期四, 05 六月 2025 09:16:24 +0800
Subject: [PATCH] 优化执行内存

---
 src/main/java/com/gs/xky/task/PurchaseOrderSyncTask.java             |   71 +++++
 src/main/java/com/gs/xky/task/ScheduledTasks.java                    |  110 ++++++++--
 .gitignore                                                           |    2 
 src/main/java/com/gs/xky/service/XkyService.java                     |   44 +++
 src/main/java/com/gs/xky/service/DeliveryNoticeService.java          |    7 
 src/main/java/com/gs/xky/service/Impl/DeliveryNoticeServiceImpl.java |   60 ++++
 src/main/java/com/gs/xky/service/PurchaseService.java                |   35 +++
 start.bat                                                            |   17 +
 start.sh                                                             |   17 +
 src/test/java/com/gs/xky/XkyApplicationTests.java                    |    8 
 README.md                                                            |  178 ++++++++++++++++
 src/main/java/com/gs/xky/config/AsyncConfig.java                     |   76 ++++++
 12 files changed, 581 insertions(+), 44 deletions(-)

diff --git a/.gitignore b/.gitignore
index 549e00a..14e7c5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,8 @@
 !**/src/main/**/target/
 !**/src/test/**/target/
 
+logs
+
 ### STS ###
 .apt_generated
 .classpath
diff --git a/README.md b/README.md
index e1d63f9..393f5e4 100644
--- a/README.md
+++ b/README.md
@@ -154,4 +154,180 @@
 
 1. 淇敼瀹炰綋绫绘枃浠朵腑鐨勫瓧娈靛畾涔�
 2. 淇敼瀵瑰簲鐨凷QL鏂囦欢涓殑琛ㄧ粨鏋勫畾涔�
-3. 鎵цSQL璇彞鏇存柊鏁版嵁搴撹〃缁撴瀯 
\ No newline at end of file
+3. 鎵цSQL璇彞鏇存柊鏁版嵁搴撹〃缁撴瀯
+
+## 鎬ц兘浼樺寲
+
+绯荤粺鍦ㄥ鐞嗗ぇ閲忔暟鎹椂鍙兘浼氶亣鍒板唴瀛樺崰鐢ㄨ繃楂樼殑闂锛岀壒鍒槸鍦ㄦ墽琛屼互涓嬫搷浣滄椂锛�
+
+1. 閲囪喘璁㈠崟鏁版嵁鍚屾(`syncPurchaseOrderDetails`鏂规硶)
+2. 閫佽揣鍗曟暟鎹鐞�
+
+### 宸插疄鏂界殑浼樺寲鎺柦
+
+1. **鍒嗘壒澶勭悊鏁版嵁**锛氬皢澶ч噺鏁版嵁鍒嗘垚灏忔壒娆¤繘琛屽鐞嗭紝鍑忓皯涓�娆℃�у唴瀛樺崰鐢�
+2. **鍙婃椂閲婃斁瀵硅薄寮曠敤**锛氬鐞嗗畬姣曞悗灏嗕笉鍐嶄娇鐢ㄧ殑瀵硅薄寮曠敤璁句负null锛屽府鍔〨C鍥炴敹鍐呭瓨
+3. **浼樺寲SQL鏌ヨ**锛氶伩鍏嶄竴娆℃�у姞杞藉ぇ閲忔暟鎹埌鍐呭瓨
+
+### JVM璋冧紭寤鸿
+
+鍦ㄥ惎鍔ㄥ簲鐢ㄦ椂锛屽彲浠ラ�氳繃浠ヤ笅JVM鍙傛暟浼樺寲鍐呭瓨浣跨敤锛�
+
+```bash
+java -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar XkyCollection.jar
+```
+
+鍙傛暟璇存槑锛�
+
+- `-Xms512m`锛氬垵濮嬪爢鍐呭瓨澶у皬涓�512MB
+- `-Xmx1024m`锛氭渶澶у爢鍐呭瓨澶у皬涓�1024MB锛堟牴鎹湇鍔″櫒瀹為檯鍙敤鍐呭瓨璋冩暣锛�
+- `-XX:MetaspaceSize=128m`锛氬垵濮嬪厓绌洪棿澶у皬涓�128MB
+- `-XX:MaxMetaspaceSize=256m`锛氭渶澶у厓绌洪棿澶у皬涓�256MB
+- `-XX:+UseG1GC`锛氫娇鐢℅1鍨冨溇鏀堕泦鍣紝閫傚悎澶у唴瀛樺簲鐢�
+- `-XX:MaxGCPauseMillis=200`锛氭渶澶C鏆傚仠鏃堕棿鐩爣涓�200姣
+
+### 鐩戞帶寤鸿
+
+1. 浣跨敤JConsole鎴朧isualVM绛夊伐鍏风洃鎺у簲鐢ㄥ唴瀛樹娇鐢ㄦ儏鍐�
+2. 鍏虫敞GC鏃ュ織锛屽垎鏋愬唴瀛樹娇鐢ㄦā寮�
+3. 鍦ㄧ敓浜х幆澧冧腑锛屽彲浠ユ坊鍔犱互涓嬪弬鏁板紑鍚疓C鏃ュ織锛�
+   ```
+   -Xloggc:/path/to/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps
+   ```
+
+## 甯歌闂鎺掓煡
+
+### 鍐呭瓨婧㈠嚭锛圤utOfMemoryError锛�
+
+濡傛灉閬囧埌鍐呭瓨婧㈠嚭闂锛�
+
+1. 妫�鏌ユ槸鍚︽湁澶ч噺鏁版嵁涓�娆℃�у姞杞藉埌鍐呭瓨
+2. 纭鏄惁鏈夊唴瀛樻硠婕忥紙瀵硅薄鍒涘缓鍚庢湭琚噴鏀撅級
+3. 澧炲姞JVM鍫嗗唴瀛樺ぇ灏�
+4. 鑰冭檻浣跨敤鍒嗛〉鏌ヨ鎴栨祦寮忓鐞嗗ぇ鏁版嵁閲�
+
+### 鏈嶅姟鍗¢】
+
+濡傛灉鏈嶅姟鍑虹幇鍗¢】锛�
+
+1. 妫�鏌ユ槸鍚︽湁闀挎椂闂磋繍琛岀殑浜嬪姟
+2. 纭鏁版嵁搴撹繛鎺ユ槸鍚︽甯搁噴鏀�
+3. 鏌ョ湅GC鏃ュ織锛岀‘璁ゆ槸鍚﹂绻佸彂鐢烣ull GC
+4. 浼樺寲鏁版嵁搴撴煡璇紝娣诲姞閫傚綋鐨勭储寮�
+
+## 鏈�浣冲疄璺�
+
+1. 閬垮厤鍦ㄩ珮宄版湡鎵ц澶ч噺鏁版嵁鍚屾鎿嶄綔
+2. 瀵逛簬瀹氭椂浠诲姟锛岄�夋嫨鍦ㄧ郴缁熻礋杞借緝浣庣殑鏃舵鎵ц
+3. 浣跨敤閫傚綋鐨勬壒澶勭悊澶у皬锛堝缓璁�100-500鏉¤褰曪級
+4. 瀹氭湡娓呯悊涓嶅啀闇�瑕佺殑鍘嗗彶鏁版嵁
+
+## 寮傛浠诲姟澶勭悊
+
+绯荤粺浣跨敤寮傛浠诲姟澶勭悊鏈哄埗鏉ユ墽琛岃�楁椂鎿嶄綔锛岄伩鍏嶉樆濉炰富绾跨▼鍜屽畾鏃朵换鍔¤皟搴︾嚎绋嬨�備富瑕佸寘鎷互涓嬪嚑涓儴鍒嗭細
+
+### 绾跨▼姹犻厤缃�
+
+绯荤粺閰嶇疆浜嗕袱涓笓鐢ㄧ嚎绋嬫睜锛�
+
+1. **閲囪喘璁㈠崟鍚屾绾跨▼姹� (purchaseTaskExecutor)**
+    - 鏍稿績绾跨▼鏁帮細1锛堢‘淇濆悓涓�鏃堕棿鍙湁涓�涓噰璐悓姝ヤ换鍔″湪鎵ц锛�
+    - 鏈�澶х嚎绋嬫暟锛�2
+    - 闃熷垪瀹归噺锛�5
+    - 鎷掔粷绛栫暐锛欳allerRunsPolicy锛堣皟鐢ㄨ�呯嚎绋嬫墽琛岋級
+
+2. **閫氱敤寮傛浠诲姟绾跨▼姹� (taskExecutor)**
+    - 鏍稿績绾跨▼鏁帮細5
+    - 鏈�澶х嚎绋嬫暟锛�10
+    - 闃熷垪瀹归噺锛�25
+    - 鎷掔粷绛栫暐锛欳allerRunsPolicy锛堣皟鐢ㄨ�呯嚎绋嬫墽琛岋級
+
+### 瀹氭椂浠诲姟浼樺寲
+
+鎵�鏈夊畾鏃朵换鍔¢兘浣跨敤寮傛鎵ц鏂瑰紡锛岄槻姝簰鐩搁樆濉烇細
+
+1. **閲囪喘璁㈠崟鍚屾浠诲姟**锛氭瘡澶�12:05鎵ц涓�娆★紝浣跨敤涓撶敤绾跨▼姹�
+2. **璁惧瀹炴椂鏁版嵁鑾峰彇**锛氭瘡5鍒嗛挓鎵ц涓�娆★紝浣跨敤閫氱敤绾跨▼姹�
+3. **琛ュ伩閫昏緫**锛氭瘡5鍒嗛挓鎵ц澶氭锛屼娇鐢ㄩ�氱敤绾跨▼姹�
+4. **閽夐拤鏁版嵁鍚屾**锛氭瘡53鍒嗛挓鎵ц涓�娆★紝浣跨敤閫氱敤绾跨▼姹�
+
+### 浠诲姟鎵ц鐘舵�佺鐞�
+
+浣跨敤 AtomicBoolean 鏍囪浠诲姟鎵ц鐘舵�侊紝閬垮厤鍚屼竴浠诲姟閲嶅鎵ц锛�
+
+```java
+private final AtomicBoolean isRunning = new AtomicBoolean(false);
+
+// 浠诲姟寮�濮嬪墠妫�鏌�
+if(!isRunning.
+
+compareAndSet(false,true)){
+        log.
+
+info("涓婁竴娆′换鍔¤繕鍦ㄦ墽琛屼腑锛岃烦杩囨湰娆℃墽琛�");
+    return;
+            }
+
+// 浠诲姟缁撴潫鍚庨噸缃姸鎬�
+            finally{
+            isRunning.
+
+set(false);
+}
+```
+
+### 寮傛浠诲姟鎵ц娴佺▼
+
+1. 瀹氭椂鍣ㄨЕ鍙戜换鍔�
+2. 妫�鏌ヤ换鍔℃槸鍚﹀凡鍦ㄨ繍琛岋紝濡傚凡杩愯鍒欒烦杩�
+3. 灏嗕换鍔℃彁浜ゅ埌鐩稿簲鐨勭嚎绋嬫睜寮傛鎵ц
+4. 瀹氭椂鍣ㄧ珛鍗宠繑鍥烇紝涓嶇瓑寰呬换鍔″畬鎴�
+5. 浠诲姟鍦ㄧ嚎绋嬫睜涓墽琛屽畬姣曞悗閲嶇疆鐘舵�佹爣璁�
+
+杩欑鏈哄埗纭繚浜嗗嵆浣挎煇涓换鍔℃墽琛屾椂闂磋緝闀匡紝涔熶笉浼氬奖鍝嶅叾浠栧畾鏃朵换鍔$殑姝e父鎵ц銆�
+
+## 鏈�鏂颁紭鍖栨洿鏂�
+
+鍦ㄦ渶杩戠殑浼樺寲涓紝鎴戜滑杩涗竴姝ユ敼杩涗簡绯荤粺鎬ц兘鍜岀ǔ瀹氭�э細
+
+1. **閫佽揣鍗曟暟鎹鐞嗕紭鍖�**
+    - 瀹炵幇浜� XkyService.GetSaveDetail() 鏂规硶鐨勫垎鎵瑰鐞�
+    - 姣忔壒澶勭悊10鏉¢�佽揣鍗曟暟鎹紝鍑忓皯鍐呭瓨鍗犵敤
+    - 澧炲己浜嗗紓甯稿鐞嗭紝鍗曟潯鏁版嵁寮傚父涓嶄細褰卞搷鏁存壒澶勭悊
+
+2. **寮傛浠诲姟澶勭悊澧炲己**
+    - 涓� DeliveryNoticeService 娣诲姞浜� @Async 娉ㄨВ鐨勫紓姝ュ鐞嗘柟娉�
+    - 瀹炵幇浜� processAsyncBatch 鏂规硶锛屾敮鎸佸苟琛屽鐞嗗鎵规暟鎹�
+    - 浼樺寲浜嗘棩蹇楄褰曪紝渚夸簬闂鎺掓煡
+
+3. **閿欒澶勭悊鏀硅繘**
+    - 鎵�鏈夊叧閿柟娉曢兘娣诲姞浜嗚缁嗙殑鏃ュ織璁板綍
+    - 瀹炵幇浜嗘洿缁嗙矑搴︾殑寮傚父鎹曡幏鍜屽鐞�
+    - 闃叉鍗曚釜浠诲姟澶辫触瀵艰嚧鏁翠釜娴佺▼涓柇
+
+### 寮傛鎵ц娴佺▼绀轰緥
+
+浠ヤ笅鏄竴涓吀鍨嬬殑寮傛鎵ц娴佺▼锛�
+
+```
+涓荤嚎绋�: 寮�濮嬪鐞�100鏉℃暟鎹�
+涓荤嚎绋�: 灏嗘暟鎹垎涓�5鎵癸紝姣忔壒20鏉�
+涓荤嚎绋�: 鎻愪氦鎵规1鍒板紓姝ョ嚎绋嬫睜
+涓荤嚎绋�: 鎻愪氦鎵规2鍒板紓姝ョ嚎绋嬫睜
+涓荤嚎绋�: 鎻愪氦鎵规3鍒板紓姝ョ嚎绋嬫睜
+涓荤嚎绋�: 鎻愪氦鎵规4鍒板紓姝ョ嚎绋嬫睜
+涓荤嚎绋�: 鎻愪氦鎵规5鍒板紓姝ョ嚎绋嬫睜
+涓荤嚎绋�: 鍏ㄩ儴鏁版嵁澶勭悊鎻愪氦瀹屾垚
+寮傛绾跨▼1: 寮�濮嬪鐞嗘壒娆�1
+寮傛绾跨▼2: 寮�濮嬪鐞嗘壒娆�2
+寮傛绾跨▼3: 寮�濮嬪鐞嗘壒娆�3
+寮傛绾跨▼1: 鎵规1澶勭悊瀹屾垚
+寮傛绾跨▼1: 寮�濮嬪鐞嗘壒娆�4
+寮傛绾跨▼2: 鎵规2澶勭悊瀹屾垚
+寮傛绾跨▼2: 寮�濮嬪鐞嗘壒娆�5
+寮傛绾跨▼3: 鎵规3澶勭悊瀹屾垚
+寮傛绾跨▼1: 鎵规4澶勭悊瀹屾垚
+寮傛绾跨▼2: 鎵规5澶勭悊瀹屾垚
+```
+
+杩欑鏂瑰紡纭繚浜嗕富绾跨▼涓嶄細琚暱鏃堕棿闃诲锛屽悓鏃跺厖鍒嗗埄鐢ㄤ簡绯荤粺璧勬簮杩涜骞惰澶勭悊銆� 
\ No newline at end of file
diff --git a/src/main/java/com/gs/xky/config/AsyncConfig.java b/src/main/java/com/gs/xky/config/AsyncConfig.java
new file mode 100644
index 0000000..25c7e61
--- /dev/null
+++ b/src/main/java/com/gs/xky/config/AsyncConfig.java
@@ -0,0 +1,76 @@
+package com.gs.xky.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 寮傛浠诲姟閰嶇疆绫�
+ * 閰嶇疆涓撶敤绾跨▼姹犲鐞嗗紓姝ヤ换鍔★紝閬垮厤闃诲Spring榛樿绾跨▼姹�
+ */
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+
+    private static final Logger log = LoggerFactory.getLogger(AsyncConfig.class);
+
+    /**
+     * 閰嶇疆閲囪喘璁㈠崟鍚屾浠诲姟涓撶敤绾跨▼姹�
+     * 浣跨敤鏈夐檺鐨勭嚎绋嬫暟锛岄伩鍏嶈祫婧愮珵浜�
+     */
+    @Bean(name = "purchaseTaskExecutor")
+    public Executor purchaseTaskExecutor() {
+        log.info("鍒涘缓閲囪喘璁㈠崟鍚屾浠诲姟涓撶敤绾跨▼姹�");
+
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        // 鏍稿績绾跨▼鏁拌缃负1锛岀‘淇濆悓涓�鏃堕棿鍙湁涓�涓噰璐悓姝ヤ换鍔″湪鎵ц
+        executor.setCorePoolSize(1);
+        // 鏈�澶х嚎绋嬫暟璁剧疆涓�2锛屽厑璁告湁闄愮殑骞跺彂
+        executor.setMaxPoolSize(2);
+        // 闃熷垪瀹归噺
+        executor.setQueueCapacity(5);
+        // 绾跨▼鍚嶇О鍓嶇紑
+        executor.setThreadNamePrefix("purchase-task-");
+        // 鎷掔粷绛栫暐锛氬綋绾跨▼姹犲凡婊℃椂锛岃皟鐢ㄨ�呯嚎绋嬫墽琛屼换鍔�
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 绛夊緟鎵�鏈変换鍔$粨鏉熷悗鍐嶅叧闂嚎绋嬫睜
+        executor.setWaitForTasksToCompleteOnShutdown(true);
+        // 绛夊緟鏃堕棿锛堢锛�
+        executor.setAwaitTerminationSeconds(60);
+        // 鍒濆鍖栫嚎绋嬫睜
+        executor.initialize();
+
+        return executor;
+    }
+
+    /**
+     * 閰嶇疆閫氱敤寮傛浠诲姟绾跨▼姹�
+     * 鐢ㄤ簬澶勭悊鍏朵粬杞婚噺绾у紓姝ヤ换鍔�
+     */
+    @Bean(name = "taskExecutor")
+    public Executor taskExecutor() {
+        log.info("鍒涘缓閫氱敤寮傛浠诲姟绾跨▼姹�");
+
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        // 鏍稿績绾跨▼鏁�
+        executor.setCorePoolSize(5);
+        // 鏈�澶х嚎绋嬫暟
+        executor.setMaxPoolSize(10);
+        // 闃熷垪瀹归噺
+        executor.setQueueCapacity(25);
+        // 绾跨▼鍚嶇О鍓嶇紑
+        executor.setThreadNamePrefix("async-task-");
+        // 鎷掔粷绛栫暐锛氬綋绾跨▼姹犲凡婊℃椂锛岃皟鐢ㄨ�呯嚎绋嬫墽琛屼换鍔�
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 鍒濆鍖栫嚎绋嬫睜
+        executor.initialize();
+
+        return executor;
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/com/gs/xky/service/DeliveryNoticeService.java b/src/main/java/com/gs/xky/service/DeliveryNoticeService.java
index e14b875..40a8ba3 100644
--- a/src/main/java/com/gs/xky/service/DeliveryNoticeService.java
+++ b/src/main/java/com/gs/xky/service/DeliveryNoticeService.java
@@ -22,4 +22,11 @@
     Integer processMesInvItemArnStatus(String factory, String company, String userCode, Long id);
 
     void processMesInvItemArnStatusAsync(List<MesInvItemArn> itemArnMinus);
+
+    /**
+     * 寮傛澶勭悊涓�鎵筂esInvItemArn鏁版嵁
+     *
+     * @param batchItems 褰撳墠鎵规鐨勬暟鎹�
+     */
+    void processAsyncBatch(List<MesInvItemArn> batchItems);
 }
diff --git a/src/main/java/com/gs/xky/service/Impl/DeliveryNoticeServiceImpl.java b/src/main/java/com/gs/xky/service/Impl/DeliveryNoticeServiceImpl.java
index 01c0d13..3b53c96 100644
--- a/src/main/java/com/gs/xky/service/Impl/DeliveryNoticeServiceImpl.java
+++ b/src/main/java/com/gs/xky/service/Impl/DeliveryNoticeServiceImpl.java
@@ -16,6 +16,9 @@
 import com.gs.xky.service.DeliveryNoticeService;
 import com.gs.xky.service.MesInvItemArnService;
 import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -34,10 +37,9 @@
 public class DeliveryNoticeServiceImpl extends ServiceImpl<DeliveryNoticeMapper, DeliveryNotice>
         implements DeliveryNoticeService {
 
+    private static final Logger log = LoggerFactory.getLogger(DeliveryNoticeServiceImpl.class);
     private final DeliveryNoticeDetailService detailService;
-
     private final MesInvItemArnService invItemArnService;
-
 
     @Override
     public boolean saveDeliveryNotice(XkyDetail xkyDetail) {
@@ -114,15 +116,59 @@
 
     @Override
     public void processMesInvItemArnStatusAsync(List<MesInvItemArn> itemArnMinus) {
+        if (itemArnMinus == null || itemArnMinus.isEmpty()) {
+            return;
+        }
+
+        // 璁板綍寮�濮嬪鐞嗙殑鏃ュ織
+        log.info("銆恜rocessMesInvItemArnStatusAsync銆戝紑濮嬪鐞唟}鏉℃暟鎹�", itemArnMinus.size());
+
+        // 鍒嗘壒澶勭悊锛屾瘡鎵规渶澶氬鐞�20鏉℃暟鎹�
+        int batchSize = 20;
+        int totalSize = itemArnMinus.size();
+        int batchCount = (totalSize + batchSize - 1) / batchSize;
+
+        for (int i = 0; i < batchCount; i++) {
+            int fromIndex = i * batchSize;
+            int toIndex = Math.min((i + 1) * batchSize, totalSize);
+            List<MesInvItemArn> batchItems = itemArnMinus.subList(fromIndex, toIndex);
+
+            log.info("銆恜rocessMesInvItemArnStatusAsync銆戝鐞嗙{}鎵规暟鎹紝鑼冨洿锛歿}-{}", i + 1, fromIndex, toIndex);
+
+            // 寮傛澶勭悊姣忔壒鏁版嵁
+            processAsyncBatch(batchItems);
+        }
+
+        log.info("銆恜rocessMesInvItemArnStatusAsync銆戝叏閮ㄦ暟鎹鐞嗘彁浜ゅ畬鎴�");
+    }
+
+    /**
+     * 寮傛澶勭悊涓�鎵筂esInvItemArn鏁版嵁
+     *
+     * @param batchItems 褰撳墠鎵规鐨勬暟鎹�
+     */
+    @Async("taskExecutor")
+    public void processAsyncBatch(List<MesInvItemArn> batchItems) {
+        log.info("銆恜rocessAsyncBatch銆戝紓姝ュ鐞唟}鏉℃暟鎹紑濮�", batchItems.size());
+        processBatch(batchItems);
+        log.info("銆恜rocessAsyncBatch銆戝紓姝ュ鐞唟}鏉℃暟鎹畬鎴�", batchItems.size());
+    }
+
+    /**
+     * 鎵归噺澶勭悊MesInvItemArn鏁版嵁
+     *
+     * @param batchItems 褰撳墠鎵规鐨勬暟鎹�
+     */
+    private void processBatch(List<MesInvItemArn> batchItems) {
         // 閬嶅巻姣忎釜 itemArn
-        itemArnMinus.forEach(itemArn -> {
+        batchItems.forEach(itemArn -> {
             try {
                 // 澶勭悊姣忎釜 itemArn
-                processMesInvItemArnStatus("1000", "1000", "PL017", itemArn.getId());
+                Integer result = processMesInvItemArnStatus("1000", "1000", "PL017", itemArn.getId());
+                log.info("銆恜rocessBatch銆戝鐞唅temArn: {}, 缁撴灉: {}", itemArn.getId(), result);
             } catch (Exception e) {
-                // 澶勭悊寮傚父锛屼緥濡傝褰曟棩蹇�
-                System.err.println("Error processing itemArn: " + itemArn.getId());
-                e.printStackTrace();
+                // 澶勭悊寮傚父锛岃褰曡缁嗘棩蹇�
+                log.error("銆恜rocessBatch銆戝鐞唅temArn: {} 寮傚父: {}", itemArn.getId(), e.getMessage(), e);
             }
         });
     }
diff --git a/src/main/java/com/gs/xky/service/PurchaseService.java b/src/main/java/com/gs/xky/service/PurchaseService.java
index 5598796..32ed2f1 100644
--- a/src/main/java/com/gs/xky/service/PurchaseService.java
+++ b/src/main/java/com/gs/xky/service/PurchaseService.java
@@ -79,8 +79,35 @@
 
         log.info("銆恠yncPurchaseOrderDetails銆戣幏鍙栧埌{}鏉¢噰璐鍗曟暟鎹�", orderDetails.size());
 
-        // 澶勭悊閲囪喘璁㈠崟鏄庣粏鏁版嵁
-        orderDetails.forEach(detail -> {
+        // 鍒嗘壒澶勭悊鏁版嵁锛屽噺灏戝唴瀛樺崰鐢�
+        int batchSize = 100; // 姣忔壒澶勭悊100鏉℃暟鎹�
+        int totalSize = orderDetails.size();
+        int batchCount = (totalSize + batchSize - 1) / batchSize; // 鍚戜笂鍙栨暣璁$畻鎵规鏁�
+
+        for (int i = 0; i < batchCount; i++) {
+            int fromIndex = i * batchSize;
+            int toIndex = Math.min((i + 1) * batchSize, totalSize);
+
+            log.info("銆恠yncPurchaseOrderDetails銆戝鐞嗙{}鎵规暟鎹紝鑼冨洿锛歿}-{}", i + 1, fromIndex, toIndex);
+
+            // 鑾峰彇褰撳墠鎵规鐨勬暟鎹�
+            List<PurchaseOrderDetail> batchDetails = orderDetails.subList(fromIndex, toIndex);
+
+            // 澶勭悊褰撳墠鎵规鐨勬暟鎹�
+            processBatch(batchDetails);
+
+            // 鎵嬪姩瑙﹀彂GC锛岄噴鏀惧唴瀛橈紙璋ㄦ厧浣跨敤锛屼粎鍦ㄥ唴瀛樼揣寮犳椂鑰冭檻锛�
+            // System.gc();
+        }
+    }
+
+    /**
+     * 鎵归噺澶勭悊閲囪喘璁㈠崟鏄庣粏鏁版嵁
+     *
+     * @param batchDetails 褰撳墠鎵规鐨勯噰璐鍗曟槑缁嗘暟鎹�
+     */
+    private void processBatch(List<PurchaseOrderDetail> batchDetails) {
+        batchDetails.forEach(detail -> {
             try {
                 // 鏍规嵁鏈夋晥鏍囧織鍜岃鍗曠姸鎬佸鐞嗕笉鍚岀殑涓氬姟閫昏緫
                 if (detail.getValidFlag() != null && detail.getValidFlag() == 0) {
@@ -113,6 +140,10 @@
 
                 // 淇濆瓨SRM閲囪喘璁㈠崟鏄庣粏
                 savePurchaseOrderDetail(detail);
+
+                // 甯姪GC鍥炴敹涓嶅啀浣跨敤鐨勫璞�
+                wrapper = null;
+                erpData = null;
             } catch (Exception e) {
                 log.error("銆恠yncPurchaseOrderDetails 澶勭悊寮傚父銆戣鍗曞彿: {}, 椤规: {}, 寮傚父: {}",
                         detail.getPoErpNo(), detail.getLineNo(), e.getMessage(), e);
diff --git a/src/main/java/com/gs/xky/service/XkyService.java b/src/main/java/com/gs/xky/service/XkyService.java
index 0ec06d5..f8e8321 100644
--- a/src/main/java/com/gs/xky/service/XkyService.java
+++ b/src/main/java/com/gs/xky/service/XkyService.java
@@ -42,7 +42,7 @@
 
     public void GetSaveDetail() throws IOException {
         long currentTimeMillis = System.currentTimeMillis();
-        long startDate = currentTimeMillis - (20 * 60 * 1000); // 璁$畻 20 鍒嗛挓鍓嶇殑鏃堕棿鎴�
+        long startDate = currentTimeMillis - (30 * 60 * 1000); // 璁$畻 120 鍒嗛挓鍓嶇殑鏃堕棿鎴�
 
         XkyCommonParam<BodyParam> param = XkyCommonParam.GetInit();
         BodyParam bodyParam = new BodyParam();
@@ -66,24 +66,58 @@
             return;
         }
 
-        deliveryNoList.forEach(deliveryNo -> {
+        log.info("銆怗etSaveDetail銆戣幏鍙栧埌{}鏉¢�佽揣鍗曟暟鎹�", deliveryNoList.size());
+
+        // 鍒嗘壒澶勭悊鏁版嵁锛屽噺灏戝唴瀛樺崰鐢�
+        int batchSize = 10; // 姣忔壒澶勭悊10鏉℃暟鎹�
+        int totalSize = deliveryNoList.size();
+        int batchCount = (totalSize + batchSize - 1) / batchSize; // 鍚戜笂鍙栨暣璁$畻鎵规鏁�
+
+        for (int i = 0; i < batchCount; i++) {
+            int fromIndex = i * batchSize;
+            int toIndex = Math.min((i + 1) * batchSize, totalSize);
+
+            log.info("銆怗etSaveDetail銆戝鐞嗙{}鎵归�佽揣鍗曟暟鎹紝鑼冨洿锛歿}-{}", i + 1, fromIndex, toIndex);
+
+            // 鑾峰彇褰撳墠鎵规鐨勬暟鎹�
+            List<XkyEntity> batchDeliveries = deliveryNoList.subList(fromIndex, toIndex);
+
+            // 澶勭悊褰撳墠鎵规鐨勬暟鎹�
+            processBatchDeliveries(batchDeliveries);
+        }
+
+        log.info("銆怗etSaveDetail銆戞墍鏈夐�佽揣鍗曞鐞嗗畬鎴�");
+    }
+
+    /**
+     * 鎵归噺澶勭悊閫佽揣鍗曟暟鎹�
+     *
+     * @param batchDeliveries 褰撳墠鎵规鐨勯�佽揣鍗曟暟鎹�
+     */
+    private void processBatchDeliveries(List<XkyEntity> batchDeliveries) {
+        batchDeliveries.forEach(deliveryNo -> {
             try {
                 if ("6".equals(deliveryNo.getStatus()) || "0".equals(deliveryNo.getLogisticsStatus())) {
-                    log.info("銆怗etSaveDetail銆戠Щ闄ら�佽揣鍗�: {}", deliveryNo.getDeliveryNo());
+                    log.info("銆恜rocessBatchDeliveries銆戠Щ闄ら�佽揣鍗�: {}", deliveryNo.getDeliveryNo());
                     remove1(deliveryNo);
                 } else if ("1".equals(deliveryNo.getStatus()) && ("2".equals(deliveryNo.getLogisticsStatus()) || "1".equals(deliveryNo.getLogisticsStatus()))) {
+                    log.info("銆恜rocessBatchDeliveries銆戝鐞嗛�佽揣鍗�: {}, 鐗╂祦鐘舵��: {}", deliveryNo.getDeliveryNo(), deliveryNo.getLogisticsStatus());
                     XkyDetail detail = getDetail(deliveryNo.getDeliveryNo());
                     deliveryNoticeService.saveDeliveryNotice(detail);
                     List<BarcodeDeliveryNo> barcodeDeliveryNos = GetBarcodeInformation(deliveryNo.getDeliveryNo());
                     barcodeInformationService.SaveBarcodeInformation(barcodeDeliveryNos, deliveryNo.getDeliveryNo());
                     //宸查�佽揪鐨勬墠鑷姩杞崲涓篗ES鍒拌揣鍗�
                     if ("2".equals(deliveryNo.getLogisticsStatus())) {
+                        log.info("銆恜rocessBatchDeliveries銆戦�佽揣鍗曞凡閫佽揪锛屾墽琛岀鏀�: {}", deliveryNo.getDeliveryNo());
                         deliveryNoticeService.callPdaReceiptBtn("閫佽揣鍗曠鏀禰BTNOK[PL017[" + deliveryNo.getDeliveryNo(), "");
                     }
                 }
             } catch (IOException e) {
-                log.error("銆怗etSaveDetail 澶勭悊寮傚父銆戦�佽揣鍗�: {}, 寮傚父: {}", deliveryNo.getDeliveryNo(), e.getMessage(), e);
-                throw new RuntimeException(e);
+                log.error("銆恜rocessBatchDeliveries銆戝鐞嗛�佽揣鍗曞紓甯�: {}, 寮傚父: {}", deliveryNo.getDeliveryNo(), e.getMessage(), e);
+                // 涓嶆姏鍑哄紓甯革紝閬垮厤涓�涓�佽揣鍗曠殑寮傚父瀵艰嚧鏁翠釜鎵规澶辫触
+            } catch (Exception e) {
+                log.error("銆恜rocessBatchDeliveries銆戝鐞嗛�佽揣鍗曟湭棰勬湡寮傚父: {}, 寮傚父: {}", deliveryNo.getDeliveryNo(), e.getMessage(), e);
+                // 涓嶆姏鍑哄紓甯革紝閬垮厤涓�涓�佽揣鍗曠殑寮傚父瀵艰嚧鏁翠釜鎵规澶辫触
             }
         });
     }
diff --git a/src/main/java/com/gs/xky/task/PurchaseOrderSyncTask.java b/src/main/java/com/gs/xky/task/PurchaseOrderSyncTask.java
index 2da0e50..dd9f7e5 100644
--- a/src/main/java/com/gs/xky/task/PurchaseOrderSyncTask.java
+++ b/src/main/java/com/gs/xky/task/PurchaseOrderSyncTask.java
@@ -8,6 +8,9 @@
 import org.springframework.stereotype.Component;
 
 import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * 閲囪喘璁㈠崟鍚屾瀹氭椂浠诲姟
@@ -18,20 +21,76 @@
     private static final Logger log = LoggerFactory.getLogger(PurchaseOrderSyncTask.class);
 
     private final PurchaseService purchaseService;
+    private final Executor purchaseTaskExecutor; // 娉ㄥ叆涓撶敤绾跨▼姹�
+
+    // 鐢ㄤ簬鏍囪浠诲姟鏄惁姝e湪鎵ц
+    private final AtomicBoolean isRunning = new AtomicBoolean(false);
 
     /**
      * 瀹氭椂鎵ц閲囪喘璁㈠崟鍚屾浠诲姟
      * 姣忓ぉ12鐐规暣鎵ц涓�娆�
      * 璁剧疆涓�12鐐�05鍒嗘墽琛岋紝閬垮厤涓庡叾浠栧畾鏃朵换鍔″啿绐�
+     * 浣跨敤寮傛鎵ц锛岄槻姝㈤樆濉炲叾浠栧畾鏃朵换鍔�
      */
     @Scheduled(cron = "0 5 12 * * ?")
     public void syncPurchaseOrders() {
-        log.info("銆恠yncPurchaseOrders銆戝紑濮嬫墽琛岄噰璐鍗曞悓姝ヤ换鍔�");
-        try {
-            purchaseService.syncPurchaseOrderDetails();
-            log.info("銆恠yncPurchaseOrders銆戦噰璐鍗曞悓姝ヤ换鍔℃墽琛屾垚鍔�");
-        } catch (IOException e) {
-            log.error("銆恠yncPurchaseOrders銆戦噰璐鍗曞悓姝ヤ换鍔℃墽琛屽紓甯�: {}", e.getMessage(), e);
+        // 濡傛灉浠诲姟宸茬粡鍦ㄨ繍琛岋紝鍒欒烦杩囨湰娆℃墽琛�
+        if (!isRunning.compareAndSet(false, true)) {
+            log.info("銆恠yncPurchaseOrders銆戜笂涓�娆′换鍔¤繕鍦ㄦ墽琛屼腑锛岃烦杩囨湰娆℃墽琛�");
+            return;
         }
+
+        log.info("銆恠yncPurchaseOrders銆戝紑濮嬫墽琛岄噰璐鍗曞悓姝ヤ换鍔�");
+
+        // 浣跨敤涓撶敤绾跨▼姹犳墽琛屽紓姝ヤ换鍔�
+        CompletableFuture.runAsync(() -> {
+            try {
+                log.info("銆恠yncPurchaseOrders銆戝紓姝ョ嚎绋嬪紑濮嬫墽琛岄噰璐鍗曞悓姝�");
+                purchaseService.syncPurchaseOrderDetails();
+                log.info("銆恠yncPurchaseOrders銆戦噰璐鍗曞悓姝ヤ换鍔℃墽琛屾垚鍔�");
+            } catch (IOException e) {
+                log.error("銆恠yncPurchaseOrders銆戦噰璐鍗曞悓姝ヤ换鍔℃墽琛屽紓甯�: {}", e.getMessage(), e);
+            } finally {
+                // 鏃犺鎴愬姛杩樻槸澶辫触锛岄兘灏嗚繍琛岀姸鎬侀噸缃�
+                isRunning.set(false);
+                log.info("銆恠yncPurchaseOrders銆戜换鍔$姸鎬佸凡閲嶇疆锛屽彲浠ユ帴鍙楁柊鐨勪换鍔�");
+            }
+        }, purchaseTaskExecutor);
+
+        // 涓嶇瓑寰呬换鍔″畬鎴愶紝绔嬪嵆杩斿洖锛岄伩鍏嶉樆濉炶皟搴︾嚎绋�
+        log.info("銆恠yncPurchaseOrders銆戦噰璐鍗曞悓姝ヤ换鍔″凡鎻愪氦鍒板紓姝ョ嚎绋嬫墽琛�");
+    }
+
+    /**
+     * 鎵嬪姩瑙﹀彂閲囪喘璁㈠崟鍚屾浠诲姟
+     * 鐢ㄤ簬绯荤粺绠$悊鍛樻墜鍔ㄨЕ鍙戝悓姝�
+     *
+     * @return 浠诲姟鏄惁宸叉彁浜ゆ墽琛�
+     */
+    public boolean manualSyncPurchaseOrders() {
+        // 濡傛灉浠诲姟宸茬粡鍦ㄨ繍琛岋紝鍒欐嫆缁濇湰娆℃墽琛�
+        if (!isRunning.compareAndSet(false, true)) {
+            log.info("銆恗anualSyncPurchaseOrders銆戜笂涓�娆′换鍔¤繕鍦ㄦ墽琛屼腑锛屾嫆缁濇湰娆℃墽琛�");
+            return false;
+        }
+
+        log.info("銆恗anualSyncPurchaseOrders銆戞墜鍔ㄨЕ鍙戦噰璐鍗曞悓姝ヤ换鍔�");
+
+        // 浣跨敤涓撶敤绾跨▼姹犳墽琛屽紓姝ヤ换鍔�
+        CompletableFuture.runAsync(() -> {
+            try {
+                log.info("銆恗anualSyncPurchaseOrders銆戝紓姝ョ嚎绋嬪紑濮嬫墽琛岄噰璐鍗曞悓姝�");
+                purchaseService.syncPurchaseOrderDetails();
+                log.info("銆恗anualSyncPurchaseOrders銆戦噰璐鍗曞悓姝ヤ换鍔℃墽琛屾垚鍔�");
+            } catch (IOException e) {
+                log.error("銆恗anualSyncPurchaseOrders銆戦噰璐鍗曞悓姝ヤ换鍔℃墽琛屽紓甯�: {}", e.getMessage(), e);
+            } finally {
+                // 鏃犺鎴愬姛杩樻槸澶辫触锛岄兘灏嗚繍琛岀姸鎬侀噸缃�
+                isRunning.set(false);
+                log.info("銆恗anualSyncPurchaseOrders銆戜换鍔$姸鎬佸凡閲嶇疆锛屽彲浠ユ帴鍙楁柊鐨勪换鍔�");
+            }
+        }, purchaseTaskExecutor);
+
+        return true;
     }
 } 
\ No newline at end of file
diff --git a/src/main/java/com/gs/xky/task/ScheduledTasks.java b/src/main/java/com/gs/xky/task/ScheduledTasks.java
index 60e53f9..3f6d295 100644
--- a/src/main/java/com/gs/xky/task/ScheduledTasks.java
+++ b/src/main/java/com/gs/xky/task/ScheduledTasks.java
@@ -8,60 +8,126 @@
 import com.gs.xky.entity.MesInvItemArn;
 import com.gs.xky.service.*;
 import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 @Component
 @RequiredArgsConstructor
 public class ScheduledTasks {
+    private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
 
     private final XkyService xkyService;
-
     private final ApiService apiService;
-
     private final MesStaffService staffService;
-
     private final DeliveryNoticeService deliveryNoticeService;
-
     private final MesInvItemArnService invItemArnService;
+    private final Executor taskExecutor; // 娉ㄥ叆閫氱敤绾跨▼姹�
+
+    // 鐢ㄤ簬鏍囪鍚勪换鍔℃槸鍚︽鍦ㄦ墽琛�
+    private final AtomicBoolean isDeviceDataRunning = new AtomicBoolean(false);
+    private final AtomicBoolean isCompensateRunning = new AtomicBoolean(false);
+    private final AtomicBoolean isDingTalkRunning = new AtomicBoolean(false);
 
     /**
      * 姣忎簲鍒嗛挓鎵ц涓�娆�
      * 鑾峰彇璁惧鏈�杩戠殑涓�鏉¤褰�
-     *
-     * @return void
-     * @author tjx
-     * @description TODO
-     * @date 2024/9/27 21:48
      */
     @Scheduled(cron = "0 0/5 * * * ?")
-    public void getDeviceRealTimeData() throws IOException {
-        xkyService.GetSaveDetail();
+    public void getDeviceRealTimeData() {
+        // 濡傛灉浠诲姟宸茬粡鍦ㄨ繍琛岋紝鍒欒烦杩囨湰娆℃墽琛�
+        if (!isDeviceDataRunning.compareAndSet(false, true)) {
+            log.info("銆恎etDeviceRealTimeData銆戜笂涓�娆′换鍔¤繕鍦ㄦ墽琛屼腑锛岃烦杩囨湰娆℃墽琛�");
+            return;
+        }
+
+        log.info("銆恎etDeviceRealTimeData銆戝紑濮嬭幏鍙栬澶囧疄鏃舵暟鎹�");
+
+        // 浣跨敤寮傛鎵ц锛岄伩鍏嶉樆濉炶皟搴︾嚎绋�
+        CompletableFuture.runAsync(() -> {
+            try {
+                xkyService.GetSaveDetail();
+                log.info("銆恎etDeviceRealTimeData銆戣幏鍙栬澶囧疄鏃舵暟鎹垚鍔�");
+            } catch (IOException e) {
+                log.error("銆恎etDeviceRealTimeData銆戣幏鍙栬澶囧疄鏃舵暟鎹紓甯�: {}", e.getMessage(), e);
+            } finally {
+                isDeviceDataRunning.set(false);
+            }
+        }, taskExecutor);
     }
 
+    /**
+     * 瀹氭椂鎵ц琛ュ伩閫昏緫
+     */
     @Scheduled(cron = "10 3,8,13,18,23,28,33,38,43,48,53,58 * * * ?")
-    public void compensateMethod() throws IOException {
-        // 琛ュ伩閫昏緫
-        List<MesInvItemArn> itemArnMinus = invItemArnService.getItemArnMinus();
-        deliveryNoticeService.processMesInvItemArnStatusAsync(itemArnMinus);
+    public void compensateMethod() {
+        // 濡傛灉浠诲姟宸茬粡鍦ㄨ繍琛岋紝鍒欒烦杩囨湰娆℃墽琛�
+        if (!isCompensateRunning.compareAndSet(false, true)) {
+            log.info("銆恈ompensateMethod銆戜笂涓�娆′换鍔¤繕鍦ㄦ墽琛屼腑锛岃烦杩囨湰娆℃墽琛�");
+            return;
+        }
+
+        log.info("銆恈ompensateMethod銆戝紑濮嬫墽琛岃ˉ鍋块�昏緫");
+
+        // 浣跨敤寮傛鎵ц锛岄伩鍏嶉樆濉炶皟搴︾嚎绋�
+        CompletableFuture.runAsync(() -> {
+            try {
+                // 琛ュ伩閫昏緫
+                List<MesInvItemArn> itemArnMinus = invItemArnService.getItemArnMinus();
+                deliveryNoticeService.processMesInvItemArnStatusAsync(itemArnMinus);
+                log.info("銆恈ompensateMethod銆戣ˉ鍋块�昏緫鎵ц鎴愬姛");
+            } catch (Exception e) {
+                log.error("銆恈ompensateMethod銆戣ˉ鍋块�昏緫鎵ц寮傚父: {}", e.getMessage(), e);
+            } finally {
+                isCompensateRunning.set(false);
+            }
+        }, taskExecutor);
     }
 
+    /**
+     * 瀹氭椂鑾峰彇閽夐拤鏁版嵁
+     */
     @Scheduled(cron = "0 0/53 * * * ?")
-    public void getDinTalkData() throws IOException {
-        DingTalkParam dingTalkParam = new DingTalkParam(1);
+    public void getDinTalkData() {
+        // 濡傛灉浠诲姟宸茬粡鍦ㄨ繍琛岋紝鍒欒烦杩囨湰娆℃墽琛�
+        if (!isDingTalkRunning.compareAndSet(false, true)) {
+            log.info("銆恎etDinTalkData銆戜笂涓�娆′换鍔¤繕鍦ㄦ墽琛屼腑锛岃烦杩囨湰娆℃墽琛�");
+            return;
+        }
 
-        DingTalkResponse<EmployeeInfo> employeeInfoDingTalkResponse = apiService.sendListRequest(dingTalkParam, EmployeeInfo.class, "http://192.168.1.64/eHR/eHRExternalService/Service.ashx");
+        log.info("銆恎etDinTalkData銆戝紑濮嬭幏鍙栭拤閽夋暟鎹�");
 
+        // 浣跨敤寮傛鎵ц锛岄伩鍏嶉樆濉炶皟搴︾嚎绋�
+        CompletableFuture.runAsync(() -> {
+            try {
+                DingTalkParam dingTalkParam = new DingTalkParam(1);
+                DingTalkResponse<EmployeeInfo> employeeInfoDingTalkResponse =
+                        apiService.sendListRequest(dingTalkParam, EmployeeInfo.class,
+                                "http://192.168.1.64/eHR/eHRExternalService/Service.ashx");
 
-        List<EmployeeInfo> collect = employeeInfoDingTalkResponse.getData().stream().filter(s -> "閫犳ⅵ鑰咃紙娴欐睙锛夌鎶�鏈夐檺鍏徃".equals(s.getCUnitName())).collect(Collectors.toList());
-        System.out.println(collect.size());
+                List<EmployeeInfo> collect = employeeInfoDingTalkResponse.getData().stream()
+                        .filter(s -> "閫犳ⅵ鑰咃紙娴欐睙锛夌鎶�鏈夐檺鍏徃".equals(s.getCUnitName()))
+                        .collect(Collectors.toList());
 
-        List<List<EmployeeInfo>> partition = ListUtil.partition(collect, 100);
+                log.info("銆恎etDinTalkData銆戣幏鍙栧埌{}鏉″憳宸ユ暟鎹�", collect.size());
 
-        partition.forEach(staffService::UpdateStaff);
+                List<List<EmployeeInfo>> partition = ListUtil.partition(collect, 100);
+                partition.forEach(staffService::UpdateStaff);
+
+                log.info("銆恎etDinTalkData銆戦拤閽夋暟鎹鐞嗗畬鎴�");
+            } catch (IOException e) {
+                log.error("銆恎etDinTalkData銆戣幏鍙栭拤閽夋暟鎹紓甯�: {}", e.getMessage(), e);
+            } finally {
+                isDingTalkRunning.set(false);
+            }
+        }, taskExecutor);
     }
 }
diff --git a/src/test/java/com/gs/xky/XkyApplicationTests.java b/src/test/java/com/gs/xky/XkyApplicationTests.java
index 035b5e2..8f2383f 100644
--- a/src/test/java/com/gs/xky/XkyApplicationTests.java
+++ b/src/test/java/com/gs/xky/XkyApplicationTests.java
@@ -58,7 +58,7 @@
     @Test
     void cs() throws IOException {
 
-        String str = "2225052002LD;222505200F75;22250520145U;2225052026EA;222505204CR8;222505204XY4;222505205WR8;222505208WCJ;222505209N46;22250520D8HK;22250520DM9W;22250520E8XU;22250520EMT7;22250520F01D;22250520FQ18;22250520J6J7;22250520JAWU;22250520JJTE;22250520JVUT;22250520KYN7;22250520QUQ2;22250520RXRY;22250520UR0E;22250520Y5W9;22250528Y85U;2225052918KK;";
+        String str = "22250529195E;22250529EQHY;22250529HCM9;222505304W8Q;222505305XRK;22250530F6UC;22250530JQ31;22250531UF8T;222506013N09;222506015051;2225060152A2;2225060152EN;222506015AM7;222506015U07;2225060162K4;222506016C4C;222506017GEM;222506017YTU;222506019RWD;22250601A216;22250601C4C3;22250601GTT8;22250601GUGU;22250601H6Y7;22250601JN9X;22250601JVW5;22250601L6R5;22250601NANG;22250601NHK4;22250601NYAL;22250601Q669;22250601RGJX;22250601VCE2;22250601W6C6;22250601WFK1;22250601WH28;22250601XE2T;22250602M0MU;";
 
 
         String[] split = str.split(";");
@@ -77,6 +77,12 @@
             ApiResponse<XkyDetail> detail = apiService.sendListRequest(param, XkyDetail.class, "https://openapi.xiekeyun.com/delivery/getDetail.json");
 
             XkyDetail deliveryNo = detail.getData();
+
+            if (deliveryNo == null) {
+                System.out.println("涓虹┖鐨勯�佽揣鍗曞彿" + s);
+                return;
+            }
+
             if ("6".equals(deliveryNo.getStatus()) || "0".equals(deliveryNo.getLogisticsStatus())) {
                 XkyEntity xkyEntity = new XkyEntity();
                 xkyEntity.setDeliveryNo(deliveryNo.getDeliveryNo());
diff --git a/start.bat b/start.bat
new file mode 100644
index 0000000..db947b1
--- /dev/null
+++ b/start.bat
@@ -0,0 +1,17 @@
+@echo off
+echo 姝e湪鍚姩閲囪喘璁㈠崟绠$悊绯荤粺...
+echo.
+
+REM 璁剧疆JVM鍙傛暟浠ヤ紭鍖栧唴瀛樹娇鐢�
+set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=200
+
+REM 鍚姩搴旂敤
+java %JAVA_OPTS% -jar XkyCollection.jar
+
+REM 濡傛灉鍚姩澶辫触锛岀瓑寰呯敤鎴锋寜閿悗閫�鍑�
+if %ERRORLEVEL% NEQ 0 (
+    echo.
+    echo 搴旂敤鍚姩澶辫触锛岃妫�鏌ラ敊璇俊鎭��
+    pause
+    exit /b %ERRORLEVEL%
+) 
\ No newline at end of file
diff --git a/start.sh b/start.sh
new file mode 100644
index 0000000..9bdcc7b
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+echo "姝e湪鍚姩閲囪喘璁㈠崟绠$悊绯荤粺..."
+echo
+
+# 璁剧疆JVM鍙傛暟浠ヤ紭鍖栧唴瀛樹娇鐢�
+JAVA_OPTS="-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
+
+# 鍚姩搴旂敤
+java $JAVA_OPTS -jar XkyCollection.jar
+
+# 濡傛灉鍚姩澶辫触锛屾樉绀洪敊璇俊鎭�
+if [ $? -ne 0 ]; then
+    echo
+    echo "搴旂敤鍚姩澶辫触锛岃妫�鏌ラ敊璇俊鎭��"
+    exit 1
+fi 
\ No newline at end of file

--
Gitblit v1.9.3