张世豪
5 小时以前 d22349714c8d199c02f336f90fba841ef8f5cd39
优化内存后最终版202511211746
已修改24个文件
1433 ■■■■ 文件已修改
bin/chuankou/Sendmsg.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/chuankou/SerialDataReceiver.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/chushihua/lunxun$PollingTask.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/chushihua/lunxun.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/publicway/ProtocolParser01$CardStatus.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/publicway/ProtocolParser01$DoorStatus.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/publicway/ProtocolParser01$FaultType.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/publicway/ProtocolParser01$ParseResult.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/publicway/ProtocolParser01$ParseResultPool.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/publicway/ProtocolParser01$WorkStatus.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/publicway/ProtocolParser01.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/publicway/SerialProtocolParser.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/xitongshezhi/kuaisuquka$2.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/xitongshezhi/kuaisuquka$3.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/xitongshezhi/kuaisuquka$4.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/xitongshezhi/kuaisuquka$SlotButtonListener.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/xitongshezhi/kuaisuquka.class 补丁 | 查看 | 原始文档 | blame | 历史
log.properties 300 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/Sendmsg.java 157 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/SerialDataReceiver.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chushihua/lunxun.java 206 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/publicway/ProtocolParser01.java 346 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/publicway/SerialProtocolParser.java 273 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/xitongshezhi/kuaisuquka.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/chuankou/Sendmsg.class
Binary files differ
bin/chuankou/SerialDataReceiver.class
Binary files differ
bin/chushihua/lunxun$PollingTask.class
Binary files differ
bin/chushihua/lunxun.class
Binary files differ
bin/publicway/ProtocolParser01$CardStatus.class
Binary files differ
bin/publicway/ProtocolParser01$DoorStatus.class
Binary files differ
bin/publicway/ProtocolParser01$FaultType.class
Binary files differ
bin/publicway/ProtocolParser01$ParseResult.class
Binary files differ
bin/publicway/ProtocolParser01$ParseResultPool.class
Binary files differ
bin/publicway/ProtocolParser01$WorkStatus.class
Binary files differ
bin/publicway/ProtocolParser01.class
Binary files differ
bin/publicway/SerialProtocolParser.class
Binary files differ
bin/xitongshezhi/kuaisuquka$2.class
Binary files differ
bin/xitongshezhi/kuaisuquka$3.class
Binary files differ
bin/xitongshezhi/kuaisuquka$4.class
Binary files differ
bin/xitongshezhi/kuaisuquka$SlotButtonListener.class
Binary files differ
bin/xitongshezhi/kuaisuquka.class
Binary files differ
log.properties
@@ -1,267 +1,33 @@
#\u64CD\u4F5C\u65E5\u5FD7\u8BB0\u5F55 - \u6700\u540E\u66F4\u65B0: Fri Nov 21 17:13:04 CST 2025
#Fri Nov 21 17:13:04 CST 2025
log_1763709005376_be67189d=[2025-11-21 15\:10\:05] 取卡操作:卡槽14被管理员取卡
log_1763709010792_533f9544=[2025-11-21 15\:10\:10] 取卡操作:卡槽14被管理员取卡
log_1763710366394_3e2ee73b=[2025-11-21 15\:32\:46] 取卡操作:卡槽1被管理员取卡
log_1763710369073_b9adfbaf=[2025-11-21 15\:32\:49] 管理员已将全部卡槽已经打开请取卡
log_1763710369761_bb324453=[2025-11-21 15\:32\:49] 取卡操作:卡槽2被管理员取卡
log_1763710374805_729bf4a3=[2025-11-21 15\:32\:54] 取卡操作:卡槽3被管理员取卡
log_1763710376872_53e825d5=[2025-11-21 15\:32\:56] 取卡操作:卡槽4被管理员取卡
log_1763710377434_30d03572=[2025-11-21 15\:32\:57] 取卡操作:卡槽5被管理员取卡
log_1763710377702_d982793b=[2025-11-21 15\:32\:57] 取卡操作:卡槽6被管理员取卡
log_1763710378251_dcba47b6=[2025-11-21 15\:32\:58] 取卡操作:卡槽7被管理员取卡
log_1763710378740_621c7d16=[2025-11-21 15\:32\:58] 取卡操作:卡槽8被管理员取卡
log_1763710378945_1f90633a=[2025-11-21 15\:32\:58] 取卡操作:卡槽9被管理员取卡
log_1763710379551_0d57ca92=[2025-11-21 15\:32\:59] 取卡操作:卡槽10被管理员取卡
log_1763710379765_c62a1f70=[2025-11-21 15\:32\:59] 取卡操作:卡槽11被管理员取卡
log_1763710380759_1a3f3a2d=[2025-11-21 15\:33\:00] 取卡操作:卡槽12被管理员取卡
log_1763710381303_43876449=[2025-11-21 15\:33\:01] 取卡操作:卡槽13被管理员取卡
log_1763710381490_e2f23d01=[2025-11-21 15\:33\:01] 取卡操作:卡槽14被管理员取卡
log_1763710381832_64ae1479=[2025-11-21 15\:33\:01] 取卡操作:卡槽15被管理员取卡
log_1763710382171_5447584c=[2025-11-21 15\:33\:02] 取卡操作:卡槽16被管理员取卡
log_1763710382679_028e4b55=[2025-11-21 15\:33\:02] 取卡操作:卡槽17被管理员取卡
log_1763710383184_87fbec0b=[2025-11-21 15\:33\:03] 取卡操作:卡槽18被管理员取卡
log_1763710383706_a4cf4dc7=[2025-11-21 15\:33\:03] 取卡操作:卡槽19被管理员取卡
log_1763710383969_ee1134f4=[2025-11-21 15\:33\:03] 取卡操作:卡槽20被管理员取卡
log_1763710384261_24848bed=[2025-11-21 15\:33\:04] 取卡操作:卡槽21被管理员取卡
log_1763710384754_dd683aa4=[2025-11-21 15\:33\:04] 取卡操作:卡槽22被管理员取卡
log_1763710385236_cb72df23=[2025-11-21 15\:33\:05] 取卡操作:卡槽23被管理员取卡
log_1763710385688_59448adc=[2025-11-21 15\:33\:05] 取卡操作:卡槽24被管理员取卡
log_1763710385869_5cd15f66=[2025-11-21 15\:33\:05] 取卡操作:卡槽25被管理员取卡
log_1763710386114_b27f7cdb=[2025-11-21 15\:33\:06] 取卡操作:卡槽26被管理员取卡
log_1763710386353_207e922a=[2025-11-21 15\:33\:06] 取卡操作:卡槽27被管理员取卡
log_1763710386567_dedb947b=[2025-11-21 15\:33\:06] 取卡操作:卡槽28被管理员取卡
log_1763710386774_fdb60ca6=[2025-11-21 15\:33\:06] 取卡操作:卡槽29被管理员取卡
log_1763710387277_ec9fe131=[2025-11-21 15\:33\:07] 取卡操作:卡槽30被管理员取卡
log_1763710392318_2b9de060=[2025-11-21 15\:33\:12] 取卡操作:卡槽31被管理员取卡
log_1763710394899_2c102a5d=[2025-11-21 15\:33\:14] 取卡操作:卡槽32被管理员取卡
log_1763710395618_9580d0cf=[2025-11-21 15\:33\:15] 取卡操作:卡槽33被管理员取卡
log_1763710395824_c45c4bb7=[2025-11-21 15\:33\:15] 取卡操作:卡槽34被管理员取卡
log_1763710396024_19f89ff8=[2025-11-21 15\:33\:16] 取卡操作:卡槽35被管理员取卡
log_1763710396205_1e9f3544=[2025-11-21 15\:33\:16] 取卡操作:卡槽36被管理员取卡
log_1763710396395_09793aa0=[2025-11-21 15\:33\:16] 取卡操作:卡槽37被管理员取卡
log_1763710396586_6da2a2be=[2025-11-21 15\:33\:16] 取卡操作:卡槽38被管理员取卡
log_1763710396751_27627af1=[2025-11-21 15\:33\:16] 取卡操作:卡槽39被管理员取卡
log_1763710396925_048a1d33=[2025-11-21 15\:33\:16] 取卡操作:卡槽40被管理员取卡
log_1763710397700_9009fb44=[2025-11-21 15\:33\:17] 取卡操作:卡槽41被管理员取卡
log_1763710398160_e8f79aa9=[2025-11-21 15\:33\:18] 取卡操作:卡槽42被管理员取卡
log_1763710398344_dba27f5c=[2025-11-21 15\:33\:18] 取卡操作:卡槽43被管理员取卡
log_1763710398527_84a6586d=[2025-11-21 15\:33\:18] 取卡操作:卡槽44被管理员取卡
log_1763710398709_ca4898fa=[2025-11-21 15\:33\:18] 取卡操作:卡槽45被管理员取卡
log_1763710398891_21c16b85=[2025-11-21 15\:33\:18] 取卡操作:卡槽46被管理员取卡
log_1763710399064_7a60cb4f=[2025-11-21 15\:33\:19] 取卡操作:卡槽47被管理员取卡
log_1763710399256_d1754fdf=[2025-11-21 15\:33\:19] 取卡操作:卡槽48被管理员取卡
log_1763710399440_adfb38c2=[2025-11-21 15\:33\:19] 取卡操作:卡槽49被管理员取卡
log_1763710399628_25b129e2=[2025-11-21 15\:33\:19] 取卡操作:卡槽50被管理员取卡
log_1763710399804_bfdf1f49=[2025-11-21 15\:33\:19] 取卡操作:卡槽51被管理员取卡
log_1763710399981_9a6fae3a=[2025-11-21 15\:33\:19] 取卡操作:卡槽52被管理员取卡
log_1763710400191_f4c40a9a=[2025-11-21 15\:33\:20] 取卡操作:卡槽53被管理员取卡
log_1763710400361_300e2593=[2025-11-21 15\:33\:20] 取卡操作:卡槽54被管理员取卡
log_1763710400545_ae5dd8e4=[2025-11-21 15\:33\:20] 取卡操作:卡槽55被管理员取卡
log_1763710400735_0041b12f=[2025-11-21 15\:33\:20] 取卡操作:卡槽56被管理员取卡
log_1763710401100_1951843e=[2025-11-21 15\:33\:21] 取卡操作:卡槽57被管理员取卡
log_1763710401283_580b32ee=[2025-11-21 15\:33\:21] 取卡操作:卡槽58被管理员取卡
log_1763710401476_d0cee988=[2025-11-21 15\:33\:21] 取卡操作:卡槽59被管理员取卡
log_1763710401684_bfb7a541=[2025-11-21 15\:33\:21] 取卡操作:卡槽60被管理员取卡
log_1763710738513_bc5737ed=[2025-11-21 15\:38\:58] 取卡操作:卡槽1被管理员取卡
log_1763710739297_f16f6cbf=[2025-11-21 15\:38\:59] 管理员已将全部卡槽已经打开请取卡
log_1763710743588_a44dd2b1=[2025-11-21 15\:39\:03] 取卡操作:卡槽2被管理员取卡
log_1763710745191_e7cd7335=[2025-11-21 15\:39\:05] 取卡操作:卡槽3被管理员取卡
log_1763710745941_38917a60=[2025-11-21 15\:39\:05] 取卡操作:卡槽4被管理员取卡
log_1763710746428_1be0c2ec=[2025-11-21 15\:39\:06] 取卡操作:卡槽5被管理员取卡
log_1763710746617_a7f4572b=[2025-11-21 15\:39\:06] 取卡操作:卡槽6被管理员取卡
log_1763710746844_6dccbbfa=[2025-11-21 15\:39\:06] 取卡操作:卡槽7被管理员取卡
log_1763710747030_7f129941=[2025-11-21 15\:39\:07] 取卡操作:卡槽8被管理员取卡
log_1763710747475_7008b86e=[2025-11-21 15\:39\:07] 取卡操作:卡槽9被管理员取卡
log_1763710747663_5bcece5b=[2025-11-21 15\:39\:07] 取卡操作:卡槽10被管理员取卡
log_1763710747839_836fdc15=[2025-11-21 15\:39\:07] 取卡操作:卡槽11被管理员取卡
log_1763710748297_819cb00d=[2025-11-21 15\:39\:08] 取卡操作:卡槽12被管理员取卡
log_1763710748481_d62eee38=[2025-11-21 15\:39\:08] 取卡操作:卡槽13被管理员取卡
log_1763710748713_7e8e1b78=[2025-11-21 15\:39\:08] 取卡操作:卡槽14被管理员取卡
log_1763710748924_6eb58529=[2025-11-21 15\:39\:08] 取卡操作:卡槽15被管理员取卡
log_1763710749180_b4f93c07=[2025-11-21 15\:39\:09] 取卡操作:卡槽16被管理员取卡
log_1763710749430_d4374f53=[2025-11-21 15\:39\:09] 取卡操作:卡槽17被管理员取卡
log_1763710749722_871e5938=[2025-11-21 15\:39\:09] 取卡操作:卡槽18被管理员取卡
log_1763710749929_a7b4b17c=[2025-11-21 15\:39\:09] 取卡操作:卡槽19被管理员取卡
log_1763710750112_41fe9c56=[2025-11-21 15\:39\:10] 取卡操作:卡槽20被管理员取卡
log_1763710750309_c9445b6a=[2025-11-21 15\:39\:10] 取卡操作:卡槽21被管理员取卡
log_1763710750497_dbfb3b50=[2025-11-21 15\:39\:10] 取卡操作:卡槽22被管理员取卡
log_1763710750865_8b47fb9d=[2025-11-21 15\:39\:10] 取卡操作:卡槽23被管理员取卡
log_1763710751038_58cc3a3b=[2025-11-21 15\:39\:11] 取卡操作:卡槽24被管理员取卡
log_1763710751222_50d2ca7f=[2025-11-21 15\:39\:11] 取卡操作:卡槽25被管理员取卡
log_1763710751396_e0d7e4d4=[2025-11-21 15\:39\:11] 取卡操作:卡槽26被管理员取卡
log_1763710751576_c31a2bb8=[2025-11-21 15\:39\:11] 取卡操作:卡槽27被管理员取卡
log_1763710751759_3257dff6=[2025-11-21 15\:39\:11] 取卡操作:卡槽28被管理员取卡
log_1763710751933_5b98b5b1=[2025-11-21 15\:39\:11] 取卡操作:卡槽29被管理员取卡
log_1763710752106_c249e495=[2025-11-21 15\:39\:12] 取卡操作:卡槽30被管理员取卡
log_1763710752288_3473b11e=[2025-11-21 15\:39\:12] 取卡操作:卡槽31被管理员取卡
log_1763710752478_bddf4a0f=[2025-11-21 15\:39\:12] 取卡操作:卡槽32被管理员取卡
log_1763710752678_03b7b598=[2025-11-21 15\:39\:12] 取卡操作:卡槽33被管理员取卡
log_1763710752882_cead4734=[2025-11-21 15\:39\:12] 取卡操作:卡槽34被管理员取卡
log_1763710753096_3e58465d=[2025-11-21 15\:39\:13] 取卡操作:卡槽35被管理员取卡
log_1763710753294_c8a39f42=[2025-11-21 15\:39\:13] 取卡操作:卡槽36被管理员取卡
log_1763710753795_011f5c48=[2025-11-21 15\:39\:13] 取卡操作:卡槽37被管理员取卡
log_1763710753999_a6bdf722=[2025-11-21 15\:39\:13] 取卡操作:卡槽38被管理员取卡
log_1763710754230_c6b37d6c=[2025-11-21 15\:39\:14] 取卡操作:卡槽39被管理员取卡
log_1763710754429_5a2cf0e3=[2025-11-21 15\:39\:14] 取卡操作:卡槽40被管理员取卡
log_1763710754634_524e289c=[2025-11-21 15\:39\:14] 取卡操作:卡槽41被管理员取卡
log_1763710754833_e252c751=[2025-11-21 15\:39\:14] 取卡操作:卡槽42被管理员取卡
log_1763710755046_ca4fdaed=[2025-11-21 15\:39\:15] 取卡操作:卡槽43被管理员取卡
log_1763710755245_f0a4c432=[2025-11-21 15\:39\:15] 取卡操作:卡槽44被管理员取卡
log_1763710755433_66d05da5=[2025-11-21 15\:39\:15] 取卡操作:卡槽45被管理员取卡
log_1763710755608_b2636ea5=[2025-11-21 15\:39\:15] 取卡操作:卡槽46被管理员取卡
log_1763710760647_d7b2c8f0=[2025-11-21 15\:39\:20] 取卡操作:卡槽47被管理员取卡
log_1763710765684_8d3d2ecb=[2025-11-21 15\:39\:25] 取卡操作:卡槽48被管理员取卡
log_1763710770722_8f84c7e9=[2025-11-21 15\:39\:30] 取卡操作:卡槽49被管理员取卡
log_1763710775759_33513110=[2025-11-21 15\:39\:35] 取卡操作:卡槽50被管理员取卡
log_1763710780797_bca992a2=[2025-11-21 15\:39\:40] 取卡操作:卡槽51被管理员取卡
log_1763710785835_7036b416=[2025-11-21 15\:39\:45] 取卡操作:卡槽52被管理员取卡
log_1763710790878_14c5f190=[2025-11-21 15\:39\:50] 取卡操作:卡槽53被管理员取卡
log_1763710795914_e6bed17f=[2025-11-21 15\:39\:55] 取卡操作:卡槽54被管理员取卡
log_1763710800956_8dce7236=[2025-11-21 15\:40\:00] 取卡操作:卡槽55被管理员取卡
log_1763710805994_a2db9e8c=[2025-11-21 15\:40\:05] 取卡操作:卡槽56被管理员取卡
log_1763710811028_a8d51351=[2025-11-21 15\:40\:11] 取卡操作:卡槽57被管理员取卡
log_1763710816051_8e739946=[2025-11-21 15\:40\:16] 取卡操作:卡槽55被管理员取卡
log_1763710821079_97f443a0=[2025-11-21 15\:40\:21] 取卡操作:卡槽58被管理员取卡
log_1763710826129_6b6a9bef=[2025-11-21 15\:40\:26] 取卡操作:卡槽59被管理员取卡
log_1763710831168_7aa2fec2=[2025-11-21 15\:40\:31] 取卡操作:卡槽60被管理员取卡
log_1763710836208_cbc1493c=[2025-11-21 15\:40\:36] 取卡操作:卡槽55被管理员取卡
log_1763711168072_7a637b83=[2025-11-21 15\:46\:08] 取卡操作:卡槽1被管理员取卡
log_1763711168170_6eb3dca2=[2025-11-21 15\:46\:08] 取卡操作:卡槽2被管理员取卡
log_1763711168270_9dfe9ac0=[2025-11-21 15\:46\:08] 取卡操作:卡槽3被管理员取卡
log_1763711168370_0e757e2d=[2025-11-21 15\:46\:08] 取卡操作:卡槽4被管理员取卡
log_1763711168470_bb1dfc2f=[2025-11-21 15\:46\:08] 取卡操作:卡槽5被管理员取卡
log_1763711168570_6d6b4073=[2025-11-21 15\:46\:08] 取卡操作:卡槽6被管理员取卡
log_1763711168669_3cfb4ace=[2025-11-21 15\:46\:08] 取卡操作:卡槽7被管理员取卡
log_1763711168769_ba4e8f33=[2025-11-21 15\:46\:08] 取卡操作:卡槽8被管理员取卡
log_1763711168870_1c83d283=[2025-11-21 15\:46\:08] 取卡操作:卡槽9被管理员取卡
log_1763711168968_16b096e0=[2025-11-21 15\:46\:08] 取卡操作:卡槽10被管理员取卡
log_1763711169070_d8dd15fb=[2025-11-21 15\:46\:09] 取卡操作:卡槽11被管理员取卡
log_1763711169169_5918a8ad=[2025-11-21 15\:46\:09] 取卡操作:卡槽12被管理员取卡
log_1763711169269_6149934f=[2025-11-21 15\:46\:09] 取卡操作:卡槽13被管理员取卡
log_1763711169369_d661fd92=[2025-11-21 15\:46\:09] 取卡操作:卡槽14被管理员取卡
log_1763711169470_4f7a20e7=[2025-11-21 15\:46\:09] 取卡操作:卡槽15被管理员取卡
log_1763711169569_be376f54=[2025-11-21 15\:46\:09] 取卡操作:卡槽16被管理员取卡
log_1763711169721_f89247f7=[2025-11-21 15\:46\:09] 取卡操作:卡槽17被管理员取卡
log_1763711169820_361b5763=[2025-11-21 15\:46\:09] 取卡操作:卡槽18被管理员取卡
log_1763711169918_58ac9aff=[2025-11-21 15\:46\:09] 取卡操作:卡槽19被管理员取卡
log_1763711170019_05f162db=[2025-11-21 15\:46\:10] 取卡操作:卡槽20被管理员取卡
log_1763711170120_400f321f=[2025-11-21 15\:46\:10] 取卡操作:卡槽21被管理员取卡
log_1763711170220_f28795df=[2025-11-21 15\:46\:10] 取卡操作:卡槽22被管理员取卡
log_1763711170320_6c1ec7b4=[2025-11-21 15\:46\:10] 取卡操作:卡槽23被管理员取卡
log_1763711170420_123cd886=[2025-11-21 15\:46\:10] 取卡操作:卡槽24被管理员取卡
log_1763711170518_e12bca59=[2025-11-21 15\:46\:10] 取卡操作:卡槽25被管理员取卡
log_1763711170619_734131eb=[2025-11-21 15\:46\:10] 取卡操作:卡槽26被管理员取卡
log_1763711170720_993b63cb=[2025-11-21 15\:46\:10] 取卡操作:卡槽27被管理员取卡
log_1763711170820_d7232328=[2025-11-21 15\:46\:10] 取卡操作:卡槽28被管理员取卡
log_1763711170920_c6a6fbf9=[2025-11-21 15\:46\:10] 取卡操作:卡槽29被管理员取卡
log_1763711171020_410bcebc=[2025-11-21 15\:46\:11] 取卡操作:卡槽30被管理员取卡
log_1763711171170_e6790075=[2025-11-21 15\:46\:11] 取卡操作:卡槽31被管理员取卡
log_1763711171269_84e5843c=[2025-11-21 15\:46\:11] 取卡操作:卡槽32被管理员取卡
log_1763711171369_c3e6d9e3=[2025-11-21 15\:46\:11] 取卡操作:卡槽33被管理员取卡
log_1763711171469_2111fab1=[2025-11-21 15\:46\:11] 取卡操作:卡槽34被管理员取卡
log_1763711171569_fdb37f62=[2025-11-21 15\:46\:11] 取卡操作:卡槽35被管理员取卡
log_1763711171669_a00d8931=[2025-11-21 15\:46\:11] 取卡操作:卡槽36被管理员取卡
log_1763711171768_993fe6d8=[2025-11-21 15\:46\:11] 取卡操作:卡槽37被管理员取卡
log_1763711171869_aa296e9d=[2025-11-21 15\:46\:11] 取卡操作:卡槽38被管理员取卡
log_1763711171969_198e8166=[2025-11-21 15\:46\:11] 取卡操作:卡槽39被管理员取卡
log_1763711172069_47f47189=[2025-11-21 15\:46\:12] 取卡操作:卡槽40被管理员取卡
log_1763711172169_a0fe6996=[2025-11-21 15\:46\:12] 取卡操作:卡槽41被管理员取卡
log_1763711172270_f829f19c=[2025-11-21 15\:46\:12] 取卡操作:卡槽42被管理员取卡
log_1763711172368_544e99ef=[2025-11-21 15\:46\:12] 取卡操作:卡槽43被管理员取卡
log_1763711172469_35271c30=[2025-11-21 15\:46\:12] 取卡操作:卡槽44被管理员取卡
log_1763711172569_007a7812=[2025-11-21 15\:46\:12] 取卡操作:卡槽45被管理员取卡
log_1763711172669_a9d07106=[2025-11-21 15\:46\:12] 取卡操作:卡槽46被管理员取卡
log_1763711172819_70bacc6a=[2025-11-21 15\:46\:12] 取卡操作:卡槽47被管理员取卡
log_1763711172919_b0739863=[2025-11-21 15\:46\:12] 取卡操作:卡槽48被管理员取卡
log_1763711173020_443f36ed=[2025-11-21 15\:46\:13] 取卡操作:卡槽49被管理员取卡
log_1763711173120_ad2656d1=[2025-11-21 15\:46\:13] 取卡操作:卡槽50被管理员取卡
log_1763711173220_cb6c90a2=[2025-11-21 15\:46\:13] 取卡操作:卡槽51被管理员取卡
log_1763711173318_5b3b3197=[2025-11-21 15\:46\:13] 取卡操作:卡槽52被管理员取卡
log_1763711173419_cb609033=[2025-11-21 15\:46\:13] 取卡操作:卡槽53被管理员取卡
log_1763711173520_f3fbfaa3=[2025-11-21 15\:46\:13] 取卡操作:卡槽54被管理员取卡
log_1763711173620_a6626517=[2025-11-21 15\:46\:13] 取卡操作:卡槽55被管理员取卡
log_1763711173720_119445bc=[2025-11-21 15\:46\:13] 取卡操作:卡槽56被管理员取卡
log_1763711173820_34259d08=[2025-11-21 15\:46\:13] 取卡操作:卡槽57被管理员取卡
log_1763711173918_9b8dd187=[2025-11-21 15\:46\:13] 取卡操作:卡槽55被管理员取卡
log_1763711173919_78e51f34=[2025-11-21 15\:46\:13] 取卡操作:卡槽58被管理员取卡
log_1763711174020_de1b1d16=[2025-11-21 15\:46\:14] 取卡操作:卡槽59被管理员取卡
log_1763711174120_269ca2e6=[2025-11-21 15\:46\:14] 取卡操作:卡槽60被管理员取卡
log_1763711174220_660bae5f=[2025-11-21 15\:46\:14] 取卡操作:卡槽55被管理员取卡
log_1763711174519_b989bf73=[2025-11-21 15\:46\:14] 取卡操作:卡槽55被管理员取卡
log_1763711174820_64ba2235=[2025-11-21 15\:46\:14] 取卡操作:卡槽55被管理员取卡
log_1763711175119_4d03fcbf=[2025-11-21 15\:46\:15] 取卡操作:卡槽55被管理员取卡
log_1763711175420_d68f2c75=[2025-11-21 15\:46\:15] 取卡操作:卡槽55被管理员取卡
log_1763711175719_e0fd7858=[2025-11-21 15\:46\:15] 取卡操作:卡槽55被管理员取卡
log_1763711176020_c70ee0f2=[2025-11-21 15\:46\:16] 取卡操作:卡槽55被管理员取卡
log_1763711176319_38854f73=[2025-11-21 15\:46\:16] 取卡操作:卡槽55被管理员取卡
log_1763711176620_41d8db8a=[2025-11-21 15\:46\:16] 取卡操作:卡槽55被管理员取卡
log_1763711179015_2952f952=[2025-11-21 15\:46\:19] 管理员已将全部卡槽已经打开请取卡
log_1763713705096_9d5670de=[2025-11-21 16\:28\:25] DDCC0008F00C515AA55AA5027A81;type2控制打开12柜门
log_1763713705463_ebe6da20=[2025-11-21 16\:28\:25] 取卡操作:卡槽12被管理员取卡
log_1763715591886_1ac9cc5a=[2025-11-21 16\:59\:51] DDCC0008F013515AA55AA502BB6F;type2控制打开19柜门
log_1763715592224_8af42a4f=[2025-11-21 16\:59\:52] 取卡操作:卡槽19被管理员取卡
log_1763715735797_38b1a47b=[2025-11-21 17\:02\:15] DDCC0008F00D515AA55AA502BA91;type2控制打开13柜门
log_1763716227580_f95bc09a=[2025-11-21 17\:10\:27] DDCC0008F00C515AA55AA5027A81;type2控制打开12柜门
log_1763716227937_a73d3b5b=[2025-11-21 17\:10\:27] 取卡操作:卡槽12被管理员取卡
log_1763716377421_6577a6ec=[2025-11-21 17\:12\:57] 取卡操作:卡槽1被管理员取卡
log_1763716377517_f6fe46de=[2025-11-21 17\:12\:57] 取卡操作:卡槽2被管理员取卡
log_1763716377617_d4676872=[2025-11-21 17\:12\:57] 取卡操作:卡槽3被管理员取卡
log_1763716377717_f8ce2321=[2025-11-21 17\:12\:57] 取卡操作:卡槽4被管理员取卡
log_1763716377817_f2002ba4=[2025-11-21 17\:12\:57] 取卡操作:卡槽5被管理员取卡
log_1763716377916_112dc429=[2025-11-21 17\:12\:57] 取卡操作:卡槽6被管理员取卡
log_1763716378018_4f02bd40=[2025-11-21 17\:12\:58] 取卡操作:卡槽7被管理员取卡
log_1763716378116_91cb3159=[2025-11-21 17\:12\:58] 取卡操作:卡槽8被管理员取卡
log_1763716378217_d21090a4=[2025-11-21 17\:12\:58] 取卡操作:卡槽9被管理员取卡
log_1763716378316_eee62d13=[2025-11-21 17\:12\:58] 取卡操作:卡槽10被管理员取卡
log_1763716378416_49dfa52f=[2025-11-21 17\:12\:58] 取卡操作:卡槽11被管理员取卡
log_1763716378516_97fd0ebf=[2025-11-21 17\:12\:58] 取卡操作:卡槽12被管理员取卡
log_1763716378617_14298d78=[2025-11-21 17\:12\:58] 取卡操作:卡槽13被管理员取卡
log_1763716378716_89f7fe99=[2025-11-21 17\:12\:58] 取卡操作:卡槽14被管理员取卡
log_1763716378867_1ee85650=[2025-11-21 17\:12\:58] 取卡操作:卡槽15被管理员取卡
log_1763716378968_de0d5066=[2025-11-21 17\:12\:58] 取卡操作:卡槽16被管理员取卡
log_1763716379065_030b8980=[2025-11-21 17\:12\:59] 取卡操作:卡槽17被管理员取卡
log_1763716379166_2af275ec=[2025-11-21 17\:12\:59] 取卡操作:卡槽18被管理员取卡
log_1763716379267_b667a29e=[2025-11-21 17\:12\:59] 取卡操作:卡槽19被管理员取卡
log_1763716379367_2498a809=[2025-11-21 17\:12\:59] 取卡操作:卡槽20被管理员取卡
log_1763716379467_bfe1598a=[2025-11-21 17\:12\:59] 取卡操作:卡槽21被管理员取卡
log_1763716379567_cb9eb62b=[2025-11-21 17\:12\:59] 取卡操作:卡槽22被管理员取卡
log_1763716379666_688ebc2f=[2025-11-21 17\:12\:59] 取卡操作:卡槽23被管理员取卡
log_1763716379766_0087530c=[2025-11-21 17\:12\:59] 取卡操作:卡槽24被管理员取卡
log_1763716379867_4611e338=[2025-11-21 17\:12\:59] 取卡操作:卡槽25被管理员取卡
log_1763716379967_fdaa10ff=[2025-11-21 17\:12\:59] 取卡操作:卡槽26被管理员取卡
log_1763716380067_7066ebe8=[2025-11-21 17\:13\:00] 取卡操作:卡槽27被管理员取卡
log_1763716380167_daa20dbf=[2025-11-21 17\:13\:00] 取卡操作:卡槽28被管理员取卡
log_1763716380266_a7c6e4f7=[2025-11-21 17\:13\:00] 取卡操作:卡槽29被管理员取卡
log_1763716380366_1dc8dacf=[2025-11-21 17\:13\:00] 取卡操作:卡槽30被管理员取卡
log_1763716380516_d28c278d=[2025-11-21 17\:13\:00] 取卡操作:卡槽31被管理员取卡
log_1763716380616_8e7dc215=[2025-11-21 17\:13\:00] 取卡操作:卡槽32被管理员取卡
log_1763716380716_2d57a4ef=[2025-11-21 17\:13\:00] 取卡操作:卡槽33被管理员取卡
log_1763716380817_27f8849c=[2025-11-21 17\:13\:00] 取卡操作:卡槽34被管理员取卡
log_1763716380915_556a565a=[2025-11-21 17\:13\:00] 取卡操作:卡槽35被管理员取卡
log_1763716381016_a66e5689=[2025-11-21 17\:13\:01] 取卡操作:卡槽36被管理员取卡
log_1763716381116_2f621f7e=[2025-11-21 17\:13\:01] 取卡操作:卡槽37被管理员取卡
log_1763716381216_8ee638c7=[2025-11-21 17\:13\:01] 取卡操作:卡槽38被管理员取卡
log_1763716381316_4a494195=[2025-11-21 17\:13\:01] 取卡操作:卡槽39被管理员取卡
log_1763716381417_d2e4fce3=[2025-11-21 17\:13\:01] 取卡操作:卡槽40被管理员取卡
log_1763716381516_ad2c841b=[2025-11-21 17\:13\:01] 取卡操作:卡槽41被管理员取卡
log_1763716381616_f769b6ee=[2025-11-21 17\:13\:01] 取卡操作:卡槽42被管理员取卡
log_1763716381716_749a04bd=[2025-11-21 17\:13\:01] 取卡操作:卡槽43被管理员取卡
log_1763716381816_36768fce=[2025-11-21 17\:13\:01] 取卡操作:卡槽44被管理员取卡
log_1763716381916_8dfccd10=[2025-11-21 17\:13\:01] 取卡操作:卡槽45被管理员取卡
log_1763716382066_05896cc1=[2025-11-21 17\:13\:02] 取卡操作:卡槽46被管理员取卡
log_1763716382167_4f94fd40=[2025-11-21 17\:13\:02] 取卡操作:卡槽47被管理员取卡
log_1763716382267_e13e3734=[2025-11-21 17\:13\:02] 取卡操作:卡槽48被管理员取卡
log_1763716382367_b5591084=[2025-11-21 17\:13\:02] 取卡操作:卡槽49被管理员取卡
log_1763716382465_8b6a0f92=[2025-11-21 17\:13\:02] 取卡操作:卡槽50被管理员取卡
log_1763716382566_039d11f4=[2025-11-21 17\:13\:02] 取卡操作:卡槽51被管理员取卡
log_1763716382667_97480314=[2025-11-21 17\:13\:02] 取卡操作:卡槽52被管理员取卡
log_1763716382767_1ce157e6=[2025-11-21 17\:13\:02] 取卡操作:卡槽53被管理员取卡
log_1763716382867_2128e536=[2025-11-21 17\:13\:02] 取卡操作:卡槽54被管理员取卡
log_1763716382967_f3041239=[2025-11-21 17\:13\:02] 取卡操作:卡槽55被管理员取卡
log_1763716383066_ea1f332b=[2025-11-21 17\:13\:03] 取卡操作:卡槽56被管理员取卡
log_1763716383166_9d894f87=[2025-11-21 17\:13\:03] 取卡操作:卡槽57被管理员取卡
log_1763716383267_b0a3c9a1=[2025-11-21 17\:13\:03] 取卡操作:卡槽58被管理员取卡
log_1763716383368_65a77f09=[2025-11-21 17\:13\:03] 取卡操作:卡槽59被管理员取卡
log_1763716383468_1d41c7bb=[2025-11-21 17\:13\:03] 取卡操作:卡槽60被管理员取卡
log_1763716384559_af7c9cc7=[2025-11-21 17\:13\:04] 管理员已将全部卡槽已经打开请取卡
#\u64CD\u4F5C\u65E5\u5FD7\u8BB0\u5F55 - \u6700\u540E\u66F4\u65B0: Fri Nov 21 17:44:41 CST 2025
#Fri Nov 21 17:44:41 CST 2025
log_1763718093181_61c0dfbe=[2025-11-21 17\:41\:33] 取卡操作:卡槽13被管理员取卡
log_1763718093533_c3563f25=[2025-11-21 17\:41\:33] 取卡操作:卡槽13被管理员取卡
log_1763718147310_e84a6b5b=[2025-11-21 17\:42\:27] 取卡操作:卡槽22被管理员取卡
log_1763718150490_e2f94107=[2025-11-21 17\:42\:30] 取卡操作:卡槽23被管理员取卡
log_1763718150843_c9147690=[2025-11-21 17\:42\:30] 取卡操作:卡槽23被管理员取卡
log_1763718198841_27d9aa77=[2025-11-21 17\:43\:18] 取卡操作:卡槽12被管理员取卡
log_1763718199155_4cd5e39f=[2025-11-21 17\:43\:19] 取卡操作:卡槽12被管理员取卡
log_1763718207706_07760e2f=[2025-11-21 17\:43\:27] DDCC0008F003515AA55AA5027A7E;type2控制打开3柜门
log_1763718208053_ee80022a=[2025-11-21 17\:43\:28] 3号卡槽取卡失败
log_1763718208759_e8be3ec0=[2025-11-21 17\:43\:28] DDCC0008F003515AA55AA5027A7E;type2控制打开3柜门
log_1763718209104_247397ce=[2025-11-21 17\:43\:29] 取卡操作:卡槽3被管理员取卡
log_1763718275945_e2a4d769=[2025-11-21 17\:44\:35] DDCC0008F012515AA55AA5027B7F;type2控制打开18柜门
log_1763718276293_034826af=[2025-11-21 17\:44\:36] 取卡操作:卡槽18被管理员取卡
log_1763718276666_18777eee=[2025-11-21 17\:44\:36] DDCC0008F017515AA55AA5027B2A;type2控制打开23柜门
log_1763718276992_c9ad983a=[2025-11-21 17\:44\:36] 取卡操作:卡槽23被管理员取卡
log_1763718277268_15912a52=[2025-11-21 17\:44\:37] DDCC0008F01C515AA55AA502BB90;type2控制打开28柜门
log_1763718277593_d9b897ba=[2025-11-21 17\:44\:37] 取卡操作:卡槽28被管理员取卡
log_1763718277892_72d570bd=[2025-11-21 17\:44\:37] DDCC0008F018515AA55AA5027BD5;type2控制打开24柜门
log_1763718278242_75327d86=[2025-11-21 17\:44\:38] 取卡操作:卡槽24被管理员取卡
log_1763718278782_a91dddda=[2025-11-21 17\:44\:38] DDCC0008F00E515AA55AA502BAA2;type2控制打开14柜门
log_1763718279143_4e4cb89a=[2025-11-21 17\:44\:39] 取卡操作:卡槽14被管理员取卡
log_1763718279202_9c58a3b9=[2025-11-21 17\:44\:39] DDCC0008F013515AA55AA502BB6F;type2控制打开19柜门
log_1763718279543_9e40ceff=[2025-11-21 17\:44\:39] 取卡操作:卡槽19被管理员取卡
log_1763718279709_4483c6c4=[2025-11-21 17\:44\:39] DDCC0008F01D515AA55AA5027B80;type2控制打开29柜门
log_1763718280043_06750db2=[2025-11-21 17\:44\:40] 取卡操作:卡槽29被管理员取卡
log_1763718280658_b6288ce6=[2025-11-21 17\:44\:40] DDCC0008F00F515AA55AA5027AB2;type2控制打开15柜门
log_1763718280993_f6f218cc=[2025-11-21 17\:44\:40] 取卡操作:卡槽15被管理员取卡
log_1763718281030_2d1edd96=[2025-11-21 17\:44\:41] DDCC0008F014515AA55AA5027B19;type2控制打开20柜门
log_1763718281392_c8b2ee8c=[2025-11-21 17\:44\:41] 取卡操作:卡槽20被管理员取卡
log_1763718281404_56d7aa71=[2025-11-21 17\:44\:41] DDCC0008F019515AA55AA502BBC5;type2控制打开25柜门
log_1763718281743_12a79e45=[2025-11-21 17\:44\:41] 取卡操作:卡槽25被管理员取卡
src/chuankou/Sendmsg.java
@@ -1,6 +1,8 @@
package chuankou;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.SwingWorker;
@@ -14,35 +16,55 @@
/**
 * 串口消息发送工具类
 * 提供高性能的串口消息发送功能,适合高频调用
 * 优化内存使用,避免长时间运行内存泄漏
 */
public class Sendmsg {
    // 静态串口服务实例
    private static volatile SerialPortService serialService = null;
    private static volatile boolean isPortOpen = false;
    private static final AtomicBoolean isPortOpen = new AtomicBoolean(false);
    
    // 改为非final,支持动态控制
    private static boolean DEBUG_MODE = false;
    private static volatile boolean DEBUG_MODE = false;
    
    // 日期格式化
    private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
    // 使用ThreadLocal保证SimpleDateFormat线程安全
    private static final ThreadLocal<SimpleDateFormat> TIME_FORMATTER =
        ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss.SSS"));
    // 缓存字符串构建器,减少对象创建
    private static final ThreadLocal<StringBuilder> STRING_BUILDER_CACHE =
        ThreadLocal.withInitial(() -> new StringBuilder(128));
    // 记录活跃的SwingWorker,便于管理
    private static final ConcurrentHashMap<String, SwingWorker<?, ?>> ACTIVE_WORKERS =
        new ConcurrentHashMap<>();
   
    
    /**发卡服务器控制打开某个柜门调用指令
     * @param int slotId柜门编号1-60
     * @param int type 1是服务器发卡,2是管理员发卡*/
    public static boolean opendoorzhiling(int slotId,int type) {
        lunxun.setSendChaxunzhiling(false);//暂停查询指令
        // 调用OpenDoor生成开门指令
        String command = OpenDoor.openOneDoor(slotId, type);
        boolean sendResult = Sendmsg.sendMessage(command);
        String mes=command+";type"+type+"控制打开"+slotId+"柜门";
        Charulog.logOperation(mes);
        if (lunxun.DEBUG_ENABLED) {
            SystemDebugDialog.appendAsciiData(mes);
        lunxun.setSendChaxunzhiling(false);//暂停查询指令
        try {
            // 调用OpenDoor生成开门指令
            String command = OpenDoor.openOneDoor(slotId, type);
            boolean sendResult = Sendmsg.sendMessage(command);
            StringBuilder mesBuilder = STRING_BUILDER_CACHE.get();
            mesBuilder.setLength(0); // 清空重用
            mesBuilder.append(command).append(";type").append(type).append("控制打开").append(slotId).append("柜门");
            String mes = mesBuilder.toString();
            Charulog.logOperation(mes);
            if (lunxun.DEBUG_ENABLED) {
                SystemDebugDialog.appendAsciiData(mes);
            }
            return sendResult;
        } finally {
            // 确保恢复查询指令
            lunxun.setSendChaxunzhiling(true);
        }
        lunxun.setSendChaxunzhiling(true);//开始查询指令
        return sendResult;
    }
    
    /**
@@ -50,13 +72,16 @@
     * @param type 操作类型:1-服务器发卡,2-管理员发卡
     */
    public static void openAllSlots(int type) {
        lunxun.setSendChaxunzhiling(false);//暂停查询指令
        lunxun.setSendChaxunzhiling(false);//暂停查询指令
        String workerKey = "openAllSlots_" + System.currentTimeMillis();
        // 使用SwingWorker在后台执行,避免阻塞UI
        SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                // 遍历所有卡槽(1-60)
                for (int slotId = 1; slotId <= 60; slotId++) {
                for (int slotId = 1; slotId <= 60 && !isCancelled(); slotId++) {
                    try {
                        // 生成开门指令
                        String command = OpenDoor.openOneDoor(slotId, type);
@@ -68,12 +93,15 @@
                            Errlog.logOperation("发送指令到卡槽 " + slotId + " 失败");
                        }
                        
                        // 间隔100ms
                        // 间隔100ms,但检查是否被取消
                        Thread.sleep(100);
                        
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break; // 被中断时退出循环
                    } catch (Exception e) {
                        Errlog.logOperation("处理卡槽 " + slotId + " 时发生错误: " + e.getMessage());
                        e.printStackTrace();
                        // 继续处理下一个卡槽,不中断循环
                    }
                }
                return null;
@@ -81,22 +109,48 @@
            
            @Override
            protected void done() {
                // 可选:完成后可以添加回调处理
                System.out.println("全部卡槽开门指令发送完成");
                String types="管理员";
                if(type==1) {
                    types="服务器指令";
                try {
                    // 清理worker引用
                    ACTIVE_WORKERS.remove(workerKey);
                    // 可选:完成后可以添加回调处理
                    if (!isCancelled()) {
                        StringBuilder messageBuilder = STRING_BUILDER_CACHE.get();
                        messageBuilder.setLength(0);
                        String types = "管理员";
                        if(type == 1) {
                            types = "服务器指令";
                        }
                        messageBuilder.append(types).append("已将全部卡槽已经打开请取卡");
                        String message = messageBuilder.toString();
                        Dingshidialog.showTimedDialog(null, 5, message);
                        Charulog.logOperation(message);
                    }
                } finally {
                    // 确保恢复查询指令
                    lunxun.setSendChaxunzhiling(true);
                }
                String message=types+"已将全部卡槽已经打开请取卡";
                Dingshidialog.showTimedDialog(null,5,message);
                Charulog.logOperation(message);
            }
        };
        
        // 记录worker便于管理
        ACTIVE_WORKERS.put(workerKey, worker);
        worker.execute();
        lunxun.setSendChaxunzhiling(true);//开始查询指令
    }
    
    /**
     * 取消所有正在执行的任务
     */
    public static void cancelAllTasks() {
        ACTIVE_WORKERS.forEach((key, worker) -> {
            if (!worker.isDone()) {
                worker.cancel(true);
            }
        });
        ACTIVE_WORKERS.clear();
    }
    
    /**
     * 设置串口服务实例
@@ -105,7 +159,7 @@
     */
    public static void setSerialService(SerialPortService service, boolean open) {
        serialService = service;
        isPortOpen = open;
        isPortOpen.set(open);
    }
    
    /**
@@ -119,7 +173,7 @@
     * 发送消息到串口(带重试机制)
     */
    public static boolean sendMessage(String message) {
        if (!isPortOpen || serialService == null) {
        if (!isPortOpen.get() || serialService == null) {
            Errlog.logOperation("[" + getCurrentTime() + "] 串口未打开,无法发送数据");
            return false;
        }
@@ -159,17 +213,21 @@
                            break;
                        }
                    } else {
                        Errlog.logOperation("[" + getCurrentTime() + "] 串口发送失败,指令: " + text.toUpperCase());
                        Errlog.logOperation("[" + getCurrentTime() + "] 串口状态 - 打开: " + isPortOpen + ", 服务: " + (serialService != null));
                        if (serialService != null) {
                            Errlog.logOperation("[" + getCurrentTime() + "] 串口服务状态 - 是否打开: " + serialService.isOpen());
                        if (DEBUG_MODE) {
                            Errlog.logOperation("[" + getCurrentTime() + "] 串口发送失败,指令: " + text.toUpperCase());
                            Errlog.logOperation("[" + getCurrentTime() + "] 串口状态 - 打开: " + isPortOpen.get() + ", 服务: " + (serialService != null));
                            if (serialService != null) {
                                Errlog.logOperation("[" + getCurrentTime() + "] 串口服务状态 - 是否打开: " + serialService.isOpen());
                            }
                        }
                        return false;
                    }
                }
            } catch (Exception e) {
                Errlog.logOperation("[" + getCurrentTime() + "] 发送异常,指令: " + text.toUpperCase());
                e.printStackTrace();
                if (DEBUG_MODE) {
                    e.printStackTrace();
                }
                return false;
            }
        }
@@ -182,7 +240,7 @@
     * @return 串口打开状态
     */
    public static boolean isPortOpen() {
        boolean open = isPortOpen && serialService != null;
        boolean open = isPortOpen.get() && serialService != null;
        if (!open && DEBUG_MODE) {
            Errlog.logOperation("[" + getCurrentTime() + "] 串口状态检查: 未打开");
        }
@@ -229,7 +287,8 @@
            return "";
        }
        
        StringBuilder sb = new StringBuilder();
        StringBuilder sb = STRING_BUILDER_CACHE.get();
        sb.setLength(0);
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
@@ -241,7 +300,7 @@
     * @return 时间字符串
     */
    private static String getCurrentTime() {
        return timeFormat.format(new Date());
        return TIME_FORMATTER.get().format(new Date());
    }
    
    /**
@@ -267,4 +326,26 @@
        DEBUG_MODE = debug;
        System.out.println("[" + getCurrentTime() + "] Sendmsg调试模式: " + (debug ? "启用" : "禁用"));
    }
    /**
     * 清理资源,防止内存泄漏
     */
    public static void cleanup() {
        cancelAllTasks();
        // 清理ThreadLocal资源
        TIME_FORMATTER.remove();
        STRING_BUILDER_CACHE.remove();
        if (DEBUG_MODE) {
            System.out.println("[" + getCurrentTime() + "] Sendmsg资源清理完成");
        }
    }
    /**
     * 获取活跃任务数量
     */
    public static int getActiveTaskCount() {
        return ACTIVE_WORKERS.size();
    }
}
src/chuankou/SerialDataReceiver.java
@@ -6,21 +6,26 @@
public class SerialDataReceiver {
    private static final int BUFFER_SIZE = 1024;
    private static byte[] staticDataBuffer = new byte[BUFFER_SIZE];
    private static int staticBufferPosition = 0;
    private static final int MIN_PACKET_LENGTH = 9;
    private static final byte[] START_MARKER = {(byte) 0xDD, (byte) 0xCC};
    // 使用非静态成员避免多线程环境下的竞争条件
    private byte[] dataBuffer = new byte[BUFFER_SIZE];
    private int bufferPosition = 0;
    private final List<byte[]> reusablePackets = new ArrayList<>();
    
    /**
     * 静态方法:接收串口原始数据并解析完整数据包
     * 实例方法:接收串口原始数据并解析完整数据包
     * @param rawData 原始数据
     * @param debugEnabled 是否启用调试
     * @param maxRawDataPrintLength 最大打印长度
     * @return 解析出的完整数据包列表,如果没有完整包则返回空列表
     */
    public static List<byte[]> receiveData(byte[] rawData, boolean debugEnabled, int maxRawDataPrintLength) {
        List<byte[]> completePackets = new ArrayList<>();
    public List<byte[]> receiveData(byte[] rawData, boolean debugEnabled, int maxRawDataPrintLength) {
        reusablePackets.clear();
        
        if (rawData == null || rawData.length == 0) {
            return completePackets;
            return reusablePackets;
        }
        
        // 打印原始接收数据(调试用)
@@ -28,88 +33,114 @@
            printRawData("收到串口原始数据", rawData, maxRawDataPrintLength);
        }
        
        // 将数据添加到缓冲区
        if (staticBufferPosition + rawData.length > staticDataBuffer.length) {
        // 检查缓冲区容量,动态处理
        if (!ensureBufferCapacity(rawData.length)) {
            // 缓冲区不足时,清理并重新开始
            System.arraycopy(staticDataBuffer, staticBufferPosition - rawData.length,
                           staticDataBuffer, 0, rawData.length);
            staticBufferPosition = rawData.length;
        } else {
            System.arraycopy(rawData, 0, staticDataBuffer, staticBufferPosition, rawData.length);
            staticBufferPosition += rawData.length;
            if (debugEnabled) {
                System.out.println("缓冲区不足,清空缓冲区重新开始");
            }
            bufferPosition = 0;
        }
        
        // 处理缓冲区中的数据并收集完整包
        processBuffer(completePackets, debugEnabled);
        // 将数据添加到缓冲区
        System.arraycopy(rawData, 0, dataBuffer, bufferPosition, rawData.length);
        bufferPosition += rawData.length;
        
        return completePackets;
        // 处理缓冲区中的数据并收集完整包
        processBuffer(reusablePackets, debugEnabled);
        return new ArrayList<>(reusablePackets);
    }
    /**
     * 确保缓冲区有足够容量,如不够则尝试压缩
     */
    private boolean ensureBufferCapacity(int required) {
        if (bufferPosition + required <= dataBuffer.length) {
            return true;
        }
        // 尝试通过压缩缓冲区来腾出空间
        int startIndex = findStartMarker();
        if (startIndex > 0) {
            compactBuffer(startIndex);
            return bufferPosition + required <= dataBuffer.length;
        }
        return false;
    }
    
    /**
     * 处理缓冲区中的数据,解析完整数据包
     */
    private static void processBuffer(List<byte[]> completePackets, boolean debugEnabled) {
        final int MIN_PACKET_LENGTH = 9;
        final byte[] START_MARKER = {(byte) 0xDD, (byte) 0xCC};
        while (staticBufferPosition >= MIN_PACKET_LENGTH) {
    private void processBuffer(List<byte[]> completePackets, boolean debugEnabled) {
        while (bufferPosition >= MIN_PACKET_LENGTH) {
            // 查找起始标记
            int startIndex = findStartMarker(START_MARKER);
            int startIndex = findStartMarker();
            if (startIndex == -1) {
                // 没有找到起始标记,清空无效数据
                if (debugEnabled) {
                    //System.out.println("未找到起始标记,清空缓冲区");
                    System.out.println("未找到起始标记,清空缓冲区");
                }
                staticBufferPosition = 0;
                bufferPosition = 0;
                return;
            }
            
            // 检查是否有足够的数据读取数据长度
            if (startIndex + 4 > staticBufferPosition) {
            if (startIndex + 4 > bufferPosition) {
                // 数据不足,等待更多数据
                compactBuffer(startIndex);
                return;
            }
            
            // 读取数据长度 (大端序)
            int dataLength = ((staticDataBuffer[startIndex + 2] & 0xFF) << 8) |
                           (staticDataBuffer[startIndex + 3] & 0xFF);
            int dataLength = ((dataBuffer[startIndex + 2] & 0xFF) << 8) |
                           (dataBuffer[startIndex + 3] & 0xFF);
            int totalPacketLength = 2 + 2 + dataLength + 2; // 起始标记2 + 数据长度2 + 数据内容 + CRC2
            
            // 检查数据长度有效性
            if (dataLength < 0 || totalPacketLength > BUFFER_SIZE) {
                if (debugEnabled) {
                    System.out.println("无效数据长度: " + dataLength + ", 跳过起始字节");
                }
                // 跳过错误的起始标记,继续查找
                compactBuffer(startIndex + 1);
                continue;
            }
            // 检查是否收到完整数据包
            if (startIndex + totalPacketLength > staticBufferPosition) {
            if (startIndex + totalPacketLength > bufferPosition) {
                // 数据包不完整,等待更多数据
                compactBuffer(startIndex);
                return;
            }
            
            // 提取完整数据包
            byte[] packet = new byte[totalPacketLength];
            System.arraycopy(staticDataBuffer, startIndex, packet, 0, totalPacketLength);
            byte[] packet = Arrays.copyOfRange(dataBuffer, startIndex, startIndex + totalPacketLength);
            
            if (debugEnabled) {
                //System.out.println("解析到完整数据包: " + bytesToHex(packet));
                System.out.println("解析到完整数据包: " + bytesToHex(packet));
            }
            
            // 添加到返回列表
            completePackets.add(packet);
            
            // 移动缓冲区位置
            int remaining = staticBufferPosition - (startIndex + totalPacketLength);
            int remaining = bufferPosition - (startIndex + totalPacketLength);
            if (remaining > 0) {
                System.arraycopy(staticDataBuffer, startIndex + totalPacketLength,
                               staticDataBuffer, 0, remaining);
                System.arraycopy(dataBuffer, startIndex + totalPacketLength,
                               dataBuffer, 0, remaining);
            }
            staticBufferPosition = remaining;
            bufferPosition = remaining;
        }
    }
    
    /**
     * 查找起始标记位置
     */
    private static int findStartMarker(byte[] startMarker) {
        for (int i = 0; i <= staticBufferPosition - startMarker.length; i++) {
            if (staticDataBuffer[i] == startMarker[0] && staticDataBuffer[i + 1] == startMarker[1]) {
    private int findStartMarker() {
        for (int i = 0; i <= bufferPosition - START_MARKER.length; i++) {
            if (dataBuffer[i] == START_MARKER[0] && dataBuffer[i + 1] == START_MARKER[1]) {
                return i;
            }
        }
@@ -119,20 +150,20 @@
    /**
     * 压缩缓冲区,将有效数据移到开头
     */
    private static void compactBuffer(int startIndex) {
        if (startIndex > 0) {
            System.arraycopy(staticDataBuffer, startIndex, staticDataBuffer, 0,
                           staticBufferPosition - startIndex);
            staticBufferPosition -= startIndex;
    private void compactBuffer(int startIndex) {
        if (startIndex > 0 && startIndex < bufferPosition) {
            System.arraycopy(dataBuffer, startIndex, dataBuffer, 0,
                           bufferPosition - startIndex);
            bufferPosition -= startIndex;
        }
    }
    
    /**
     * 打印原始数据(调试用)
     */
    private static void printRawData(String prefix, byte[] data, int maxPrintLength) {
    private void printRawData(String prefix, byte[] data, int maxPrintLength) {
        if (data == null || data.length == 0) {
            //System.out.println(prefix + ": 空数据");
            System.out.println(prefix + ": 空数据");
            return;
        }
        
@@ -148,13 +179,13 @@
            sb.append("... [截断,总长度: ").append(data.length).append("]");
        }
        
        //System.out.println(sb.toString());
        System.out.println(sb.toString());
    }
    
    /**
     * 工具方法:字节数组转十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
@@ -165,16 +196,23 @@
    /**
     * 清空缓冲区(避免内存泄漏)
     */
    public static void clearBuffer() {
        staticBufferPosition = 0;
    public void clearBuffer() {
        bufferPosition = 0;
        // 可选:清空缓冲区内容
        Arrays.fill(staticDataBuffer, (byte) 0);
        Arrays.fill(dataBuffer, (byte) 0);
    }
    
    /**
     * 获取当前缓冲区状态
     */
    public static int getBufferStatus() {
        return staticBufferPosition;
    public int getBufferStatus() {
        return bufferPosition;
    }
    /**
     * 获取缓冲区容量
     */
    public int getBufferCapacity() {
        return dataBuffer.length;
    }
}
src/chushihua/lunxun.java
@@ -7,6 +7,7 @@
import publicway.QueryData;
import xitongshezhi.SystemDebugDialog;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -16,6 +17,7 @@
 * 用于定时向所有卡槽发送查询指令
 * 支持暂停和恢复功能,检查串口连接状态
 * 新增:不同卡槽状态使用不同查询频率
 * 优化:内存管理和长时间运行稳定性
 */
public class lunxun {
    private static volatile boolean isRunning = false;
@@ -24,14 +26,6 @@
    private static Thread pollingThread;
    private static int pollingInterval = 100; // 默认轮询间隔
    public static boolean sendChaxunzhiling=true;//是否向串口发送查询指令
    public static boolean isSendChaxunzhiling() {
        return sendChaxunzhiling;
    }
    public static void setSendChaxunzhiling(boolean sendChaxunzhiling) {
        lunxun.sendChaxunzhiling = sendChaxunzhiling;
    }
    // 卡槽相关常量
    private static final int MIN_SLOT = 1;
@@ -44,6 +38,15 @@
    // 性能优化:查询指令缓存
    private static final Map<Integer, String> queryCommandCache = new ConcurrentHashMap<>();
    // 内存优化:缓存大小限制和清理机制
    private static final int MAX_CACHE_SIZE = 100;
    private static final long CACHE_CLEANUP_INTERVAL = 60000; // 1分钟清理一次
    private static long lastCleanupTime = 0;
    // 错误日志限流机制
    private static final Map<String, Long> lastErrorLogTime = new ConcurrentHashMap<>();
    private static final long ERROR_LOG_INTERVAL = 5000; // 相同错误5秒内只记录一次
    // 调试模式控制
    public static  boolean DEBUG_ENABLED = false;
@@ -52,6 +55,14 @@
    private static final int NO_CARD_QUERY_INTERVAL = 100;    // 无卡卡槽查询间隔:100ms
    private static final int HAS_CARD_QUERY_INTERVAL = 10000; // 有卡卡槽查询间隔:10秒
    private static final Map<Integer, Long> lastQueryTimeMap = new ConcurrentHashMap<>(); // 记录每个卡槽的最后查询时间
    public static boolean isSendChaxunzhiling() {
        return sendChaxunzhiling;
    }
    public static void setSendChaxunzhiling(boolean sendChaxunzhiling) {
        lunxun.sendChaxunzhiling = sendChaxunzhiling;
    }
    /**
     * 检查串口连接状态 - 优化版本,添加重试机制
@@ -76,11 +87,11 @@
                }
                serialConnected = true;
            } else {
                Errlog.logOperation("串口连接失败 - 串口未打开");
                logErrorWithRateLimit("serial_connection_failed", "串口连接失败 - 串口未打开");
                serialConnected = false;
            }
        } catch (Exception e) {
            Errlog.logOperation("串口连接检查异常: " + e.getMessage());
            logErrorWithRateLimit("serial_connection_exception", "串口连接检查异常: " + e.getMessage());
            serialConnected = false;
        }
@@ -117,9 +128,12 @@
        // 启动前严格检查串口连接
        if (!checkSerialConnectionWithRetry()) {
            Errlog.logOperation("串口未连接,无法启动轮询查询");
            logErrorWithRateLimit("start_polling_serial_failed", "串口未连接,无法启动轮询查询");
            return false;
        }
        // 启动前先清理一次内存
        performCleanup();
        // 从配置中获取轮询间隔
        loadPollingIntervalFromConfig();
@@ -137,7 +151,7 @@
            pollingThread.start(); 
            return true;
        } catch (Exception e) {
            Errlog.logOperation("启动轮询查询线程时发生异常: " + e.getMessage());
            logErrorWithRateLimit("start_polling_thread_exception", "启动轮询查询线程时发生异常: " + e.getMessage());
            isRunning = false;
            shouldStop.set(true);
            return false;
@@ -174,15 +188,15 @@
                pollingThread.join(3000); // 等待3秒
                // 检查线程是否还在运行
                if (pollingThread.isAlive()) {
                    Errlog.logOperation("轮询线程未在3秒内停止,标记为守护线程并忽略");
                    logErrorWithRateLimit("polling_thread_stop_timeout", "轮询线程未在3秒内停止,标记为守护线程并忽略");
                    // 不强制停止,而是确保它是守护线程
                    pollingThread.setDaemon(true);
                }
            } catch (InterruptedException e) {
                Errlog.logOperation("停止轮询查询时被中断: " + e.getMessage());
                logErrorWithRateLimit("stop_polling_interrupted", "停止轮询查询时被中断: " + e.getMessage());
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                Errlog.logOperation("停止轮询线程时发生异常: " + e.getMessage());
                logErrorWithRateLimit("stop_polling_exception", "停止轮询线程时发生异常: " + e.getMessage());
            } finally {
                pollingThread = null;
            }
@@ -234,7 +248,7 @@
        // 恢复前检查串口连接
        if (!checkSerialConnectionWithRetry()) {
            Errlog.logOperation("串口未连接,无法恢复轮询查询");
            logErrorWithRateLimit("resume_polling_serial_failed", "串口未连接,无法恢复轮询查询");
            return false;
        }
@@ -276,7 +290,7 @@
     */
    public static void setPollingInterval(int interval) {
        if (interval < 10) {
            Errlog.logOperation("轮询间隔不能小于10ms");
            logErrorWithRateLimit("polling_interval_too_small", "轮询间隔不能小于10ms");
            return;
        }
@@ -328,7 +342,7 @@
                //System.out.println("配置系统未初始化,使用默认轮询间隔: " + pollingInterval + "ms");
            }
        } catch (Exception e) {
            Errlog.logOperation("加载轮询间隔配置失败: " + e.getMessage());
            logErrorWithRateLimit("load_polling_interval_failed", "加载轮询间隔配置失败: " + e.getMessage());
            //System.out.println("使用默认轮询间隔: " + pollingInterval + "ms");
        }
    }
@@ -351,12 +365,13 @@
    /**
     * 轮询任务内部类 - 优化版本
     * 支持不同状态卡槽的不同查询频率
     * 优化:内存管理和重用对象
     */
    private static class PollingTask implements Runnable {
        private int currentIndex = 0; // 当前索引,用于遍历slotArray
        private int consecutiveFailures = 0; // 连续失败次数
        private static final int MAX_CONSECUTIVE_FAILURES = 5; // 最大连续失败次数
        private final StringBuilder debugBuilder = new StringBuilder(100); // 重用 StringBuilder
        @Override
        public void run() {
@@ -378,15 +393,20 @@
                    // 定期检查串口连接状态(每10次循环检查一次)
                    if (currentIndex % 10 == 0 && !checkSerialConnectionWithRetry()) {
                        Errlog.logOperation("串口连接断开,暂停轮询");
                        logErrorWithRateLimit("serial_disconnected", "串口连接断开,暂停轮询");
                        pausePolling();
                        continue;
                    }
                    // 定期清理缓存(每100次循环清理一次)
                    if (currentIndex % 100 == 0) {
                        cleanupOldCache();
                    }
                    // 获取卡槽数组
                    Fkj[] slotArray = SlotManager.getSlotArray();
                    if (slotArray == null || slotArray.length == 0) {
                        Errlog.logOperation("卡槽数组未初始化");
                        logErrorWithRateLimit("slot_array_not_initialized", "卡槽数组未初始化");
                        Thread.sleep(pollingInterval);
                        continue;
                    }
@@ -427,18 +447,18 @@
                                        } else {
                                            status = "无卡";
                                        }
                                        if (DEBUG_ENABLED) {
                                            StringBuilder debugMsg = new StringBuilder(50);
                                            debugMsg.append("Slot ").append(slotNumber)
                                                    .append(" (").append(status).append(") 查询成功,间隔: ")
                                                    .append(queryInterval).append("ms\n");
                                            SystemDebugDialog.appendAsciiData(debugMsg.toString());
                                        }
                                        // 使用重用的 StringBuilder 构建调试信息
                                        debugBuilder.setLength(0);
                                        debugBuilder.append("Slot ").append(slotNumber)
                                                   .append(" (").append(status).append(") 查询成功,间隔: ")
                                                   .append(queryInterval).append("ms\n");
                                        SystemDebugDialog.appendAsciiData(debugBuilder.toString());
                                    }
                                } else {
                                    consecutiveFailures++;
                                    if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
                                        Errlog.logOperation("lunxun连续失败次数过多,暂停轮询");
                                        logErrorWithRateLimit("consecutive_failures", "lunxun连续失败次数过多,暂停轮询");
                                        pausePolling();
                                        break;
                                    }
@@ -460,7 +480,7 @@
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    Errlog.logOperation("轮询查询过程中发生异常: " + e.getMessage());
                    logErrorWithRateLimit("polling_exception", "轮询查询过程中发生异常: " + e.getMessage());
                    consecutiveFailures++;
                    // 发生异常时等待一段时间再继续
@@ -508,12 +528,12 @@
                        return false;
                    }
                } else {
                    Errlog.logOperation("生成的查询指令为空,卡槽: " + slotNumber);
                    logErrorWithRateLimit("empty_query_command", "生成的查询指令为空,卡槽: " + slotNumber);
                    return false;
                }
            } catch (Exception e) {
                Errlog.logOperation("发送查询指令到卡槽 " + slotNumber + " 时发生异常: " + e.getMessage());
                logErrorWithRateLimit("send_query_exception", "发送查询指令到卡槽 " + slotNumber + " 时发生异常: " + e.getMessage());
                // 发生异常时更新串口连接状态
                serialConnected = false;
                return false;
@@ -528,13 +548,13 @@
     */
    public static boolean sendImmediateQuery(int slotNumber) {
        if (slotNumber < MIN_SLOT || slotNumber > MAX_SLOT) {
            Errlog.logOperation("卡槽编号必须在" + MIN_SLOT + "-" + MAX_SLOT + "之间");
            logErrorWithRateLimit("invalid_slot_number", "卡槽编号必须在" + MIN_SLOT + "-" + MAX_SLOT + "之间");
            return false;
        }
        // 检查串口连接
        if (!checkSerialConnectionWithRetry()) {
            Errlog.logOperation("串口未连接,无法发送查询指令");
            logErrorWithRateLimit("immediate_query_serial_failed", "串口未连接,无法发送查询指令");
            return false;
        }
@@ -555,16 +575,16 @@
                    }
                    return true;
                } else {
                    Errlog.logOperation("立即查询失败 - 发送指令到卡槽 " + slotNumber + " 失败");
                    logErrorWithRateLimit("immediate_query_send_failed", "立即查询失败 - 发送指令到卡槽 " + slotNumber + " 失败");
                    return false;
                }
            } else {
                Errlog.logOperation("立即查询失败 - 生成的查询指令为空,卡槽: " + slotNumber);
                logErrorWithRateLimit("immediate_query_empty_command", "立即查询失败 - 生成的查询指令为空,卡槽: " + slotNumber);
                return false;
            }
        } catch (Exception e) {
            Errlog.logOperation("立即查询卡槽 " + slotNumber + " 时发生异常: " + e.getMessage());
            logErrorWithRateLimit("immediate_query_exception", "立即查询卡槽 " + slotNumber + " 时发生异常: " + e.getMessage());
            return false;
        }
    }
@@ -576,7 +596,7 @@
    public static int sendImmediateQueryToAll() {
        // 检查串口连接
        if (!checkSerialConnectionWithRetry()) {
            Errlog.logOperation("串口未连接,无法发送批量查询指令");
            logErrorWithRateLimit("batch_query_serial_failed", "串口未连接,无法发送批量查询指令");
            return 0;
        }
@@ -629,7 +649,7 @@
        if (connected) {
            //            //System.out.println("串口连接状态已设置为: 已连接");
        } else {
            Errlog.logOperation("串口连接状态已设置为: 未连接");
            logErrorWithRateLimit("serial_disconnected_external", "串口连接状态已设置为: 未连接");
            // 如果串口断开且轮询正在运行,自动暂停轮询
            if (isRunning && !isPaused) {
                pausePolling();
@@ -668,9 +688,9 @@
            }
        }
        return String.format("轮询状态: %s, 串口: %s, 间隔: %dms, 指令缓存: %d, 卡槽范围: %d-%d, 无卡: %d(100ms), 有卡: %d(10s)",
        return String.format("轮询状态: %s, 串口: %s, 间隔: %dms, 指令缓存: %d, 卡槽范围: %d-%d, 无卡: %d(100ms), 有卡: %d(10s)\n%s",
                status, serialStatus, pollingInterval, cacheSize, MIN_SLOT, MAX_SLOT, 
                noCardCount, hasCardCount);
                noCardCount, hasCardCount, getMemoryStatus());
    }
    /**
@@ -699,7 +719,7 @@
            if (isPaused) {
                // 恢复前检查串口连接
                if (!checkSerialConnectionWithRetry()) {
                    Errlog.logOperation("串口未连接,无法恢复轮询查询");
                    logErrorWithRateLimit("external_resume_serial_failed", "串口未连接,无法恢复轮询查询");
                    return false;
                }
@@ -756,7 +776,7 @@
     */
    public static void setNoCardQueryInterval(int interval) {
        if (interval < 10) {
            Errlog.logOperation("无卡卡槽查询间隔不能小于10ms");
            logErrorWithRateLimit("no_card_interval_too_small", "无卡卡槽查询间隔不能小于10ms");
            return;
        }
        // 注意:这里只是设置常量,实际运行时需要重新启动轮询才能生效
@@ -769,7 +789,7 @@
     */
    public static void setHasCardQueryInterval(int interval) {
        if (interval < 1000) {
            Errlog.logOperation("有卡卡槽查询间隔不能小于1000ms");
            logErrorWithRateLimit("has_card_interval_too_small", "有卡卡槽查询间隔不能小于1000ms");
            return;
        }
        // 注意:这里只是设置常量,实际运行时需要重新启动轮询才能生效
@@ -783,4 +803,102 @@
    public static void setDEBUG_ENABLED(boolean dEBUG_ENABLED) {
        DEBUG_ENABLED = dEBUG_ENABLED;
    }
    // ==================== 新增内存优化方法 ====================
    /**
     * 清理旧缓存 - 防止内存无限增长
     */
    private static void cleanupOldCache() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastCleanupTime < CACHE_CLEANUP_INTERVAL) {
            return;
        }
        lastCleanupTime = currentTime;
        // 清理长时间未使用的查询时间记录
        long cleanupThreshold = currentTime - 300000; // 5分钟未使用
        lastQueryTimeMap.entrySet().removeIf(entry ->
            currentTime - entry.getValue() > cleanupThreshold
        );
        // 限制查询指令缓存大小
        if (queryCommandCache.size() > MAX_CACHE_SIZE) {
            Iterator<Map.Entry<Integer, String>> iterator = queryCommandCache.entrySet().iterator();
            int itemsToRemove = queryCommandCache.size() - MAX_CACHE_SIZE;
            for (int i = 0; i < itemsToRemove && iterator.hasNext(); i++) {
                iterator.next();
                iterator.remove();
            }
        }
        // 清理错误日志限流记录
        lastErrorLogTime.entrySet().removeIf(entry ->
            currentTime - entry.getValue() > 300000 // 5分钟
        );
    }
    /**
     * 限流错误日志 - 防止大量重复日志占用内存
     */
    private static void logErrorWithRateLimit(String errorKey, String message) {
        long currentTime = System.currentTimeMillis();
        Long lastTime = lastErrorLogTime.get(errorKey);
        if (lastTime == null || currentTime - lastTime > ERROR_LOG_INTERVAL) {
            Errlog.logOperation(message);
            lastErrorLogTime.put(errorKey, currentTime);
            // 清理过期的错误记录
            if (lastErrorLogTime.size() > 50) {
                lastErrorLogTime.entrySet().removeIf(entry ->
                    currentTime - entry.getValue() > 300000 // 5分钟
                );
            }
        }
    }
    /**
     * 获取内存状态信息
     */
    public static String getMemoryStatus() {
        Runtime runtime = Runtime.getRuntime();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;
        long maxMemory = runtime.maxMemory();
        return String.format("内存使用: %.2fMB/%.2fMB (最大: %.2fMB), 缓存: 时间记录=%d, 指令缓存=%d, 错误记录=%d",
            usedMemory / (1024.0 * 1024.0),
            totalMemory / (1024.0 * 1024.0),
            maxMemory / (1024.0 * 1024.0),
            lastQueryTimeMap.size(),
            queryCommandCache.size(),
            lastErrorLogTime.size());
    }
    /**
     * 手动触发内存清理
     */
    public static void performCleanup() {
        // 清理查询时间记录中长时间未查询的卡槽
        long cleanupThreshold = System.currentTimeMillis() - 3600000; // 1小时
        lastQueryTimeMap.entrySet().removeIf(entry ->
            entry.getValue() < cleanupThreshold
        );
        // 清空查询指令缓存
        queryCommandCache.clear();
        // 清空错误日志限流记录
        lastErrorLogTime.clear();
        // 建议系统进行垃圾回收(但不强制)
        System.gc();
        if (DEBUG_ENABLED) {
            SystemDebugDialog.appendAsciiData("执行内存清理完成\n");
        }
    }
}
src/publicway/ProtocolParser01.java
@@ -1,14 +1,20 @@
package publicway;
import java.util.ArrayList;
import java.util.List;
import chuankou.SerialPortService;
import chushihua.SlotManager;
import dialog.Errlog;
public class ProtocolParser01 {
    // 缓存常用字符串减少重复创建
    private static final String[] WORK_STATUS_DESC = {"无效", "待机", "充电", "充满", "故障", "授权到期", "通信超时", "未知状态"};
    private static final String[] DOOR_STATUS_DESC = {"未知状态", "开门状态", "关门状态"};
    private static final String[] CARD_STATUS_DESC = {"无卡", "有卡", "读卡错误(卡非法)", "未知状态"};
    // StringBuilder 对象池
    private static final ThreadLocal<StringBuilder> stringBuilderPool =
        ThreadLocal.withInitial(() -> new StringBuilder(512));
    /**
     * 新增:直接使用字节数组解析的方法(避免字符串转换)
     * 优化后的字节数组解析方法
     */
    public static ParseResult parseDDCC01Data(byte[] packetData) {
        if (packetData == null || packetData.length < 18) {
@@ -20,45 +26,49 @@
            throw new IllegalArgumentException("非DDCC协议数据");
        }
        ParseResult result = ParseResultPool.borrowObject();
        try {
            // 跳过包头DDCC (2字节),直接使用剩余数据
            byte[] dataBytes = new byte[packetData.length - 2];
            System.arraycopy(packetData, 2, dataBytes, 0, dataBytes.length);
            if (dataBytes.length < 16) {
            // 直接使用原数组,避免创建新数组
            if (packetData.length < 18) { // 2(包头) + 16(最小数据长度)
                throw new IllegalArgumentException("数据长度不足");
            }
            // 2. 解析各个字段
            int dataLength = parseDataLength(dataBytes);
            int hostAddress = parseHostAddress(dataBytes);
            int slotNumber = parseSlotNumber(dataBytes);
            int functionCode = parseFunctionCode(dataBytes);
            WorkStatus workStatus = parseWorkStatus(dataBytes);
            DoorStatus doorStatus = parseDoorStatus(dataBytes);
            CardStatus cardStatus = parseCardStatus(dataBytes);
            int cardStatusChange = parseCardStatusChange(dataBytes);
            String cardNumber = parseCardNumber(dataBytes);
            List<FaultType> faults = parseFaults(dataBytes);
            double voltage = parseVoltage(dataBytes);
            double current = parseCurrent(dataBytes);
            // 解析各个字段
            int dataLength = parseDataLength(packetData, 2);
            int hostAddress = parseHostAddress(packetData, 4);
            int slotNumber = parseSlotNumber(packetData, 5);
            int functionCode = parseFunctionCode(packetData, 6);
            // 3. 验证功能码
            // 验证功能码
            if (functionCode != 0x01) {
                throw new IllegalArgumentException("非01功能码数据");
            }
            return new ParseResult(hostAddress, slotNumber, workStatus, doorStatus,
                    cardStatus, cardStatusChange, cardNumber,
                    faults, voltage, current, dataLength);
            WorkStatus workStatus = parseWorkStatus(packetData, 7);
            DoorStatus doorStatus = parseDoorStatus(packetData, 8);
            CardStatus cardStatus = parseCardStatus(packetData, 9);
            int cardStatusChange = parseCardStatusChange(packetData, 10);
            String cardNumber = parseCardNumber(packetData, 13);
            List<FaultType> faults = parseFaults(packetData, 15);
            double voltage = parseVoltage(packetData, 16);
            double current = parseCurrent(packetData, 17);
            // 重用 ParseResult 对象
            result.reset(hostAddress, slotNumber, workStatus, doorStatus,
                        cardStatus, cardStatusChange, cardNumber,
                        faults, voltage, current, dataLength);
            return result;
        } catch (Exception e) {
            // 发生异常时归还对象
            ParseResultPool.returnObject(result);
            throw new RuntimeException("解析数据时发生错误: " + e.getMessage(), e);
        }
    }
    /**
     * 保留原有方法用于兼容性
     * 优化后的字符串解析方法
     */
    public static ParseResult parseDDCC01Data(String hexData) {
        if (hexData == null || hexData.isEmpty()) {
@@ -70,6 +80,7 @@
            throw new IllegalArgumentException("非DDCC协议数据");
        }
        ParseResult result = ParseResultPool.borrowObject();
        try {
            // 1. 移除包头DDCC进行解析
            String dataWithoutHeader = hexData.substring(4);
@@ -80,179 +91,162 @@
            }
            // 2. 解析各个字段
            int dataLength = parseDataLength(dataBytes);
            int hostAddress = parseHostAddress(dataBytes);
            int slotNumber = parseSlotNumber(dataBytes);
            int functionCode = parseFunctionCode(dataBytes);
            WorkStatus workStatus = parseWorkStatus(dataBytes);
            DoorStatus doorStatus = parseDoorStatus(dataBytes);
            CardStatus cardStatus = parseCardStatus(dataBytes);
            int cardStatusChange = parseCardStatusChange(dataBytes);
            String cardNumber = parseCardNumber(dataBytes);
            List<FaultType> faults = parseFaults(dataBytes);
            double voltage = parseVoltage(dataBytes);
            double current = parseCurrent(dataBytes);
            int dataLength = parseDataLength(dataBytes, 0);
            int hostAddress = parseHostAddress(dataBytes, 2);
            int slotNumber = parseSlotNumber(dataBytes, 3);
            int functionCode = parseFunctionCode(dataBytes, 4);
            // 3. 验证功能码
            if (functionCode != 0x01) {
                throw new IllegalArgumentException("非01功能码数据");
            }
            return new ParseResult(hostAddress, slotNumber, workStatus, doorStatus,
                    cardStatus, cardStatusChange, cardNumber,
                    faults, voltage, current, dataLength);
            WorkStatus workStatus = parseWorkStatus(dataBytes, 5);
            DoorStatus doorStatus = parseDoorStatus(dataBytes, 6);
            CardStatus cardStatus = parseCardStatus(dataBytes, 7);
            int cardStatusChange = parseCardStatusChange(dataBytes, 8);
            String cardNumber = parseCardNumber(dataBytes, 11);
            List<FaultType> faults = parseFaults(dataBytes, 13);
            double voltage = parseVoltage(dataBytes, 14);
            double current = parseCurrent(dataBytes, 15);
            result.reset(hostAddress, slotNumber, workStatus, doorStatus,
                        cardStatus, cardStatusChange, cardNumber,
                        faults, voltage, current, dataLength);
            return result;
        } catch (Exception e) {
            ParseResultPool.returnObject(result);
            throw new RuntimeException("解析数据时发生错误: " + e.getMessage(), e);
        }
    }
    /**
     * CRC校验
     * 根据协议:CRC16校验从功能码之后一直到CRC16之前的数据
     */
    @SuppressWarnings("unused")
    private static boolean validateCRC(String hexData) {
        try {
            // CRC在最后4个字符
            String receivedCRC = hexData.substring(hexData.length() - 6);
            byte[] cmdBytes = HexUtil.hexStringToBytes(hexData.replace(receivedCRC,""));
            String crc = HexUtil.calculate(cmdBytes)+"00";
            //System.out.println("收到的完整数据是:"+hexData);
            //System.out.println("收到数据校验码是:"+receivedCRC);
            //System.out.println("校验码是:"+crc);
            return receivedCRC.equalsIgnoreCase(crc);
        } catch (Exception e) {
            Errlog.logOperation("CRC校验异常: " + e.getMessage());
            return false;
        }
    }
    /**
     * 解析数据长度(2字节)
     * 数据长度是从该字节之后开始到CRC16之前数据字节数
     */
    private static int parseDataLength(byte[] data) {
        if (data.length < 2) {
    private static int parseDataLength(byte[] data, int offset) {
        if (data.length < offset + 2) {
            throw new IllegalArgumentException("数据长度不足,无法解析数据长度");
        }
        return ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
        return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
    }
    /**
     * 解析主机地址(1字节)
     */
    private static int parseHostAddress(byte[] data) {
        if (data.length < 3) {
    private static int parseHostAddress(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析主机地址");
        }
        return data[2] & 0xFF;
        return data[offset] & 0xFF;
    }
    /**
     * 解析卡槽编号(1字节)
     */
    private static int parseSlotNumber(byte[] data) {
        if (data.length < 4) {
    private static int parseSlotNumber(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析卡槽编号");
        }
        return data[3] & 0xFF;
        return data[offset] & 0xFF;
    }
    /**
     * 解析功能码(1字节)
     */
    private static int parseFunctionCode(byte[] data) {
        if (data.length < 5) {
    private static int parseFunctionCode(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析功能码");
        }
        return data[4] & 0xFF;
        return data[offset] & 0xFF;
    }
    /**
     * 解析工作状态(1字节)
     */
    private static WorkStatus parseWorkStatus(byte[] data) {
        if (data.length < 6) {
    private static WorkStatus parseWorkStatus(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析工作状态");
        }
        int statusValue = data[5] & 0xFF;
        int statusValue = data[offset] & 0xFF;
        return WorkStatus.fromValue(statusValue);
    }
    /**
     * 解析在位状态/门状态(1字节)
     */
    private static DoorStatus parseDoorStatus(byte[] data) {
        if (data.length < 7) {
    private static DoorStatus parseDoorStatus(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析在位状态");
        }
        int statusValue = data[6] & 0xFF;
        int statusValue = data[offset] & 0xFF;
        return DoorStatus.fromValue(statusValue);
    }
    /**
     * 解析卡状态(1字节)
     */
    private static CardStatus parseCardStatus(byte[] data) {
        if (data.length < 8) {
    private static CardStatus parseCardStatus(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析卡状态");
        }
        int statusValue = data[7] & 0xFF;
        int statusValue = data[offset] & 0xFF;
        return CardStatus.fromValue(statusValue);
    }
    /**
     * 解析卡状态变更(1字节)
     */
    private static int parseCardStatusChange(byte[] data) {
        if (data.length < 9) {
    private static int parseCardStatusChange(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析卡状态变更");
        }
        return data[8] & 0xFF;
        return data[offset] & 0xFF;
    }
    /**
     * 解析卡号(卡号3 + 卡号4)
     */
    private static String parseCardNumber(byte[] data) {
        if (data.length < 13) {
    private static String parseCardNumber(byte[] data, int offset) {
        if (data.length < offset + 2) {
            throw new IllegalArgumentException("数据长度不足,无法解析卡号");
        }
        // 索引11:卡号3,索引12:卡号4
        byte cardNumber3 = data[11];
        byte cardNumber4 = data[12];
        return String.format("%02X%02X", cardNumber3 & 0xFF, cardNumber4 & 0xFF);
        // 直接返回字符串,避免创建临时对象
        char[] hexChars = new char[4];
        hexChars[0] = Character.forDigit((data[offset] >> 4) & 0xF, 16);
        hexChars[1] = Character.forDigit(data[offset] & 0xF, 16);
        hexChars[2] = Character.forDigit((data[offset + 1] >> 4) & 0xF, 16);
        hexChars[3] = Character.forDigit(data[offset + 1] & 0xF, 16);
        return new String(hexChars).toUpperCase();
    }
    /**
     * 解析故障信息(1字节)
     */
    private static List<FaultType> parseFaults(byte[] data) {
        if (data.length < 14) {
    private static List<FaultType> parseFaults(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析故障信息");
        }
        int faultByte = data[13] & 0xFF;
        List<FaultType> faults = new ArrayList<>();
        int faultByte = data[offset] & 0xFF;
        List<FaultType> faults = new ArrayList<>(5); // 预分配容量
        for (FaultType fault : FaultType.values()) {
            if ((faultByte & fault.getBitMask()) != 0) {
                faults.add(fault);
            }
        }
        return faults;
    }
    /**
     * 解析电压值(1字节)
     */
    private static double parseVoltage(byte[] data) {
        if (data.length < 15) {
    private static double parseVoltage(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析电压");
        }
        int voltageValue = data[14] & 0xFF;
        int voltageValue = data[offset] & 0xFF;
        // 50mV/bit 转换为伏特
        return voltageValue * 0.05;
    }
@@ -260,18 +254,16 @@
    /**
     * 解析电流值(1字节)
     */
    private static double parseCurrent(byte[] data) {
        if (data.length < 16) {
    private static double parseCurrent(byte[] data, int offset) {
        if (data.length < offset + 1) {
            throw new IllegalArgumentException("数据长度不足,无法解析电流");
        }
        int currentValue = data[15] & 0xFF;
        int currentValue = data[offset] & 0xFF;
        // 10mA/bit 转换为安培
        return currentValue * 0.01;
    }
    /**
     * 工作状态枚举
     */
    // 枚举类保持不变...
    public enum WorkStatus {
        INVALID(0, "无效"),
        STANDBY(1, "待机"),
@@ -290,13 +282,8 @@
            this.description = description;
        }
        public int getValue() {
            return value;
        }
        public String getDescription() {
            return description;
        }
        public int getValue() { return value; }
        public String getDescription() { return description; }
        public static WorkStatus fromValue(int value) {
            for (WorkStatus status : values()) {
@@ -308,9 +295,6 @@
        }
    }
    /**
     * 门状态枚举
     */
    public enum DoorStatus {
        UNKNOWN(0, "δ֪״̬"),
        DOOR_OPEN(1, "开门状态"),
@@ -324,13 +308,8 @@
            this.description = description;
        }
        public int getValue() {
            return value;
        }
        public String getDescription() {
            return description;
        }
        public int getValue() { return value; }
        public String getDescription() { return description; }
        public static DoorStatus fromValue(int value) {
            for (DoorStatus status : values()) {
@@ -342,9 +321,6 @@
        }
    }
    /**
     * 卡状态枚举
     */
    public enum CardStatus {
        NO_CARD(0, "无卡"),
        HAS_CARD(1, "有卡"),
@@ -359,13 +335,8 @@
            this.description = description;
        }
        public int getValue() {
            return value;
        }
        public String getDescription() {
            return description;
        }
        public int getValue() { return value; }
        public String getDescription() { return description; }
        public static CardStatus fromValue(int value) {
            for (CardStatus status : values()) {
@@ -377,9 +348,6 @@
        }
    }
    /**
     * 故障类型枚举
     */
    public enum FaultType {
        INSERT_ERROR(0x01, "插卡错误"),
        OVER_CURRENT(0x02, "过流"),
@@ -395,17 +363,12 @@
            this.description = description;
        }
        public int getBitMask() {
            return bitMask;
        }
        public String getDescription() {
            return description;
        }
        public int getBitMask() { return bitMask; }
        public String getDescription() { return description; }
    }
    /**
     * 解析结果类 - 添加对象池支持
     * 优化后的解析结果类
     */
    public static class ParseResult {
        private int hostAddress;
@@ -420,29 +383,12 @@
        private double current;
        private int dataLength;
        // 默认构造器用于对象池
        // 重用列表对象
        private final List<FaultType> faultList = new ArrayList<>(5);
        private final List<String> faultDescList = new ArrayList<>(5);
        public ParseResult() {}
        public ParseResult(int hostAddress, int slotNumber, WorkStatus workStatus,
                DoorStatus doorStatus, CardStatus cardStatus, int cardStatusChange,
                String cardNumber, List<FaultType> faults, double voltage,
                double current, int dataLength) {
            this.hostAddress = hostAddress;
            this.slotNumber = slotNumber;
            this.workStatus = workStatus;
            this.doorStatus = doorStatus;
            this.cardStatus = cardStatus;
            this.cardStatusChange = cardStatusChange;
            this.cardNumber = cardNumber;
            this.faults = faults;
            this.voltage = voltage;
            this.current = current;
            this.dataLength = dataLength;
        }
        /**
         * 重置方法,用于对象重用
         */
        public void reset(int hostAddress, int slotNumber, WorkStatus workStatus, 
                         DoorStatus doorStatus, CardStatus cardStatus, int cardStatusChange,
                         String cardNumber, List<FaultType> faults, double voltage, 
@@ -454,10 +400,16 @@
            this.cardStatus = cardStatus;
            this.cardStatusChange = cardStatusChange;
            this.cardNumber = cardNumber;
            this.faults = faults;
            this.voltage = voltage;
            this.current = current;
            this.dataLength = dataLength;
            // 重用故障列表
            this.faultList.clear();
            if (faults != null) {
                this.faultList.addAll(faults);
            }
            this.faults = this.faultList;
        }
        // Getter方法
@@ -477,21 +429,24 @@
         * 获取故障的中文描述列表
         */
        public List<String> getFaultDescriptions() {
            List<String> descriptions = new ArrayList<>();
            faultDescList.clear();
            for (FaultType fault : faults) {
                descriptions.add(fault.getDescription());
                faultDescList.add(fault.getDescription());
            }
            return descriptions;
            return faultDescList;
        }
        /**
         * 获取故障的中文描述字符串
         */
        public String getFaultsString() {
            if (faults == null || faults.isEmpty()) {
            if (faults.isEmpty()) {
                return "无故障";
            }
            StringBuilder sb = new StringBuilder();
            StringBuilder sb = stringBuilderPool.get();
            sb.setLength(0);
            for (int i = 0; i < faults.size(); i++) {
                if (i > 0) sb.append(", ");
                sb.append(faults.get(i).getDescription());
@@ -501,7 +456,9 @@
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            StringBuilder sb = stringBuilderPool.get();
            sb.setLength(0);
            sb.append("1.主机地址:").append(String.format("%02X", hostAddress));
            sb.append("2.卡槽编号:").append(slotNumber);
            sb.append("3.工作状态:").append(workStatus.getDescription())
@@ -515,34 +472,31 @@
            sb.append("8.故障:").append(getFaultsString());
            sb.append("9.电压:").append(String.format("%.2f", voltage));
            sb.append("10.电流:").append(String.format("%.2f", current));
            sb.append("数据长度:").append(dataLength).append(" 字节");
//            System.out.println(sb.toString());
            return sb.toString();
            sb.append("数据长度:").append(dataLength).append(" 字节");
            return sb.toString();
        }
        
        public void fuzhi() {
            SlotManager.gengxinshuxingzhi(
            SlotManager.gengxinshuxingzhi(
                    slotNumber,    // 卡槽编号
                    cardNumber,    // 卡编号
                    String.valueOf(cardStatus.getValue()),       // 是否有卡0无卡,1有卡,-1未知
                    String.valueOf(workStatus.getValue()),    // 工作状态0.无效1.待机;2.充电;3.充满;4.故障;5.授权到期;6.通信超时
                    String.valueOf(workStatus.getValue()),    // 工作状态
                    String.format("%.2f", voltage),      // 电压
                    String.format("%.2f", current),       // 电流
                    getFaultsString()        // 故障1插卡错误;2过流;3,门控故障;4过压;5欠压;
                    );
                    getFaultsString()        // 故障
            );
        }
    }
    /**
     * 简单的对象池实现
     * 改进的对象池实现
     */
    public static class ParseResultPool {
        private static final int POOL_SIZE = 10;
        private static final int POOL_SIZE = 20;
        private static final java.util.concurrent.BlockingQueue<ParseResult> pool = 
            new java.util.concurrent.ArrayBlockingQueue<>(POOL_SIZE);
            new java.util.concurrent.LinkedBlockingQueue<>(POOL_SIZE);
        
        static {
            // 预创建对象
@@ -557,9 +511,17 @@
        }
        
        public static void returnObject(ParseResult result) {
            if (result != null && !pool.offer(result)) {
                // 池已满,不回收
            if (result != null) {
                // 清理状态
                result.reset(0, 0, WorkStatus.UNKNOWN, DoorStatus.UNKNOWN,
                           CardStatus.UNKNOWN, 0, "", null, 0.0, 0.0, 0);
                // 非阻塞式归还
                pool.offer(result);
            }
        }
        public static int getPoolSize() {
            return pool.size();
        }
    }
}
src/publicway/SerialProtocolParser.java
@@ -1,4 +1,5 @@
package publicway;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
@@ -27,15 +28,15 @@
    private static final byte FUNCTION_82 = (byte) 0x82; // 单板升级使能
    private static final byte FUNCTION_83 = (byte) 0x83;   // 单板升级数据包
    
    // 数据缓冲区,用于处理粘包
    // 数据缓冲区,用于处理粘包 - 改为直接ByteArrayOutputStream管理
    private byte[] dataBuffer = new byte[1024];
    private int bufferPosition = 0;
    
    // 数据接收队列
    private BlockingQueue<byte[]> dataQueue = new ArrayBlockingQueue<>(100);
    // 数据接收队列 - 限制队列大小防止内存无限增长
    private BlockingQueue<byte[]> dataQueue = new ArrayBlockingQueue<>(50);
    
    // 批量处理队列
    private final BlockingQueue<byte[]> batchQueue = new ArrayBlockingQueue<>(1000);
    // 批量处理队列 - 限制队列大小
    private final BlockingQueue<byte[]> batchQueue = new ArrayBlockingQueue<>(200);
    private final ScheduledExecutorService batchExecutor = 
        Executors.newSingleThreadScheduledExecutor();
    
@@ -46,12 +47,18 @@
    // 重用StringBuilder减少对象创建
    private final StringBuilder hexBuilder = new StringBuilder(256);
    
    // 内存监控计数器
    private long lastMemoryCheckTime = 0;
    private static final long MEMORY_CHECK_INTERVAL = 30000; // 30秒检查一次
    // 对象池,减少对象创建
    private final Object packetPoolLock = new Object();
    /**
     * 启动解析器
     */
    public void start() {
        if (isRunning) {
            //System.out.println("串口协议解析器已经在运行中");
            return;
        }
        
@@ -63,8 +70,6 @@
        processorThread = new Thread(this::processPackets, "Serial-Protocol-Parser");
        processorThread.setDaemon(true);
        processorThread.start();
        //System.out.println("串口协议解析器已启动 - 独立于轮询状态运行");
    }
    
    /**
@@ -99,11 +104,16 @@
        }
        
        // 清空队列和缓冲区
        clearQueues();
        bufferPosition = 0;
    }
    /**
     * 清空所有队列,释放内存
     */
    private void clearQueues() {
        dataQueue.clear();
        batchQueue.clear();
        bufferPosition = 0;
        //System.out.println("串口协议解析器已停止");
    }
    
    /**
@@ -126,9 +136,31 @@
            return;
        }
        
        // 将数据添加到批量队列 - 确保始终执行
        // 检查队列状态,避免内存无限增长
        if (batchQueue.size() > batchQueue.remainingCapacity() * 0.8) {
            // 队列接近满时,丢弃最老的数据
            if (!batchQueue.isEmpty()) {
                batchQueue.poll(); // 移除一个旧数据
            }
        }
        // 将数据添加到批量队列
        if (!batchQueue.offer(rawData)) {
            System.err.println("批量队列已满,丢弃数据");
            // 队列已满时的处理
            handleQueueFull();
        }
    }
    /**
     * 处理队列满的情况
     */
    private void handleQueueFull() {
        // 清空队列重新开始,避免内存泄漏
        clearQueues();
        bufferPosition = 0; // 重置缓冲区
        if (lunxun.DEBUG_ENABLED) {
            SystemDebugDialog.appendAsciiData("警告:数据处理队列已满,已清空队列重新开始");
        }
    }
    
@@ -140,39 +172,105 @@
            return;
        }
        
        // 批量处理数据
        java.util.List<byte[]> batch = new java.util.ArrayList<>(100);
        batchQueue.drainTo(batch, 100);
        for (byte[] rawData : batch) {
            // 将数据添加到缓冲区
            if (bufferPosition + rawData.length > dataBuffer.length) {
                // 缓冲区不足时,清理并重新开始
                System.arraycopy(dataBuffer, bufferPosition - rawData.length, dataBuffer, 0, rawData.length);
                bufferPosition = rawData.length;
            } else {
        try {
            // 批量处理数据,限制每次处理的最大数量
            int maxBatchSize = 50;
            java.util.List<byte[]> batch = new java.util.ArrayList<>(maxBatchSize);
            batchQueue.drainTo(batch, maxBatchSize);
            for (byte[] rawData : batch) {
                // 检查缓冲区容量,避免溢出
                if (bufferPosition + rawData.length > dataBuffer.length) {
                    // 缓冲区不足时的处理
                    if (rawData.length > dataBuffer.length) {
                        // 单条数据超过缓冲区大小,直接处理或丢弃
                        handleOversizedPacket(rawData);
                        continue;
                    } else {
                        // 移动有效数据到缓冲区开头
                        compactBuffer(0);
                    }
                }
                // 将数据添加到缓冲区
                System.arraycopy(rawData, 0, dataBuffer, bufferPosition, rawData.length);
                bufferPosition += rawData.length;
                // 处理缓冲区中的数据
                processBuffer();
            }
            
            // 处理缓冲区中的数据
            processBuffer();
            // 定期检查内存
            checkMemory();
        } catch (Exception e) {
            System.err.println("批量处理数据时发生异常: " + e.getMessage());
            // 发生异常时重置状态
            resetParserState();
        }
        // 定期检查内存
        checkMemory();
    }
    /**
     * 处理过大的数据包
     */
    private void handleOversizedPacket(byte[] oversizedData) {
        // 对于过大的数据包,直接尝试查找起始标记
        int startIndex = findStartMarkerInArray(oversizedData, 0);
        if (startIndex != -1) {
            // 找到起始标记,将剩余数据放入缓冲区
            int remainingLength = oversizedData.length - startIndex;
            if (remainingLength <= dataBuffer.length) {
                System.arraycopy(oversizedData, startIndex, dataBuffer, 0, remainingLength);
                bufferPosition = remainingLength;
                processBuffer();
            }
        }
        // 否则丢弃该数据包
    }
    /**
     * 在指定数组中查找起始标记
     */
    private int findStartMarkerInArray(byte[] data, int startPos) {
        for (int i = startPos; i <= data.length - START_MARKER.length; i++) {
            if (data[i] == START_MARKER[0] && data[i + 1] == START_MARKER[1]) {
                return i;
            }
        }
        return -1;
    }
    /**
     * 重置解析器状态
     */
    private void resetParserState() {
        bufferPosition = 0;
        clearQueues();
    }
    
    /**
     * 内存监控
     */
    private void checkMemory() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastMemoryCheckTime < MEMORY_CHECK_INTERVAL) {
            return;
        }
        lastMemoryCheckTime = currentTime;
        Runtime runtime = Runtime.getRuntime();
        long usedMem = runtime.totalMemory() - runtime.freeMemory();
        long maxMem = runtime.maxMemory();
        
        if (usedMem > maxMem * 0.8) {
            //System.out.println("内存使用率超过80%,当前使用: " + (usedMem / 1024 / 1024) + "MB");
        if (usedMem > maxMem * 0.75) {
            // 内存使用率超过75%时进行垃圾回收
            System.gc();
            if (lunxun.DEBUG_ENABLED) {
                SystemDebugDialog.appendAsciiData("内存使用率超过75%,已触发垃圾回收。使用内存: " +
                    (usedMem / 1024 / 1024) + "MB");
            }
        }
    }
    
@@ -180,7 +278,10 @@
     * 处理缓冲区中的数据,解析完整数据包
     */
    private void processBuffer() {
        while (bufferPosition >= MIN_PACKET_LENGTH) {
        int processedCount = 0;
        final int MAX_PACKETS_PER_BATCH = 20; // 限制每次处理的最大包数量
        while (bufferPosition >= MIN_PACKET_LENGTH && processedCount < MAX_PACKETS_PER_BATCH) {
            // 查找起始标记
            int startIndex = findStartMarker();
            if (startIndex == -1) {
@@ -200,6 +301,13 @@
            int dataLength = ((dataBuffer[startIndex + 2] & 0xFF) << 8) | (dataBuffer[startIndex + 3] & 0xFF);
            int totalPacketLength = 2 + 2 + dataLength + 2; // 起始标记2 + 数据长度2 + 数据内容 + CRC2
            
            // 检查数据长度是否合理
            if (dataLength < 0 || totalPacketLength > dataBuffer.length) {
                // 数据长度异常,跳过这个包
                compactBuffer(startIndex + 1);
                continue;
            }
            // 检查是否收到完整数据包
            if (startIndex + totalPacketLength > bufferPosition) {
                // 数据包不完整,等待更多数据
@@ -208,16 +316,15 @@
            }
            
            // 提取完整数据包
            byte[] packet = new byte[totalPacketLength];
            System.arraycopy(dataBuffer, startIndex, packet, 0, totalPacketLength);
            // 将数据包放入队列供解析
            try {
            byte[] packet = extractPacket(startIndex, totalPacketLength);
            if (packet != null) {
                // 将数据包放入队列供解析
                if (!dataQueue.offer(packet)) {
                    System.err.println("数据队列已满,丢弃数据包");
                    // 队列已满,释放packet引用
                    packet = null;
                    handleDataQueueFull();
                    return;
                }
            } catch (Exception e) {
                System.err.println("放入数据队列时发生异常: " + e.getMessage());
            }
            
            // 移动缓冲区位置
@@ -226,6 +333,29 @@
                System.arraycopy(dataBuffer, startIndex + totalPacketLength, dataBuffer, 0, remaining);
            }
            bufferPosition = remaining;
            processedCount++;
        }
    }
    /**
     * 提取数据包,重用byte数组减少对象创建
     */
    private byte[] extractPacket(int startIndex, int totalPacketLength) {
        byte[] packet = new byte[totalPacketLength];
        System.arraycopy(dataBuffer, startIndex, packet, 0, totalPacketLength);
        return packet;
    }
    /**
     * 处理数据队列满的情况
     */
    private void handleDataQueueFull() {
        // 丢弃队列中最老的数据
        dataQueue.poll();
        if (lunxun.DEBUG_ENABLED) {
            SystemDebugDialog.appendAsciiData("数据解析队列已满,丢弃最老数据包");
        }
    }
    
@@ -245,7 +375,7 @@
     * 压缩缓冲区,将有效数据移到开头
     */
    private void compactBuffer(int startIndex) {
        if (startIndex > 0) {
        if (startIndex > 0 && bufferPosition > startIndex) {
            System.arraycopy(dataBuffer, startIndex, dataBuffer, 0, bufferPosition - startIndex);
            bufferPosition -= startIndex;
        }
@@ -267,7 +397,7 @@
                break;
            } catch (Exception e) {
                System.err.println("处理数据包时发生异常: " + e.getMessage());
                e.printStackTrace();
                // 继续运行,不退出线程
            }
        }
        
@@ -278,8 +408,12 @@
     * 解析数据包并根据功能码调用相应方法
     */
    private void parsePacket(byte[] packet) {
        if (packet == null || packet.length < MIN_PACKET_LENGTH) {
            return;
        }
        try {
            SerialPortService.getReceivedDataCount();
            SerialPortService.getReceivedDataCount();
            // 解析基本字段
            byte hostAddress = packet[4];        // 主机地址
            byte slotAddress = packet[5];        // 卡槽地址
@@ -290,7 +424,7 @@
            // 返回值数据
            int returnValueLength = dataLength - 3; // N-3 (减去主机地址、卡槽地址、功能码)
            byte[] returnValue = null;
            if (returnValueLength > 0) {
            if (returnValueLength > 0 && returnValueLength <= packet.length - 7) {
                returnValue = new byte[returnValueLength];
                System.arraycopy(packet, 7, returnValue, 0, returnValueLength);
            }
@@ -301,12 +435,12 @@
                    if (returnValue != null) {
                        // 使用优化的字节数组解析方法,避免字符串转换
                        ParseResult rst = ProtocolParser01.parseDDCC01Data(packet);
                        rst.fuzhi();
//                        System.out.println(rst.toString());
                        if (lunxun.DEBUG_ENABLED) {
                            SystemDebugDialog.appendAsciiData(rst.toString());
                        if (rst != null) {
                            rst.fuzhi();
                            if (lunxun.DEBUG_ENABLED) {
                                SystemDebugDialog.appendAsciiData(rst.toString());
                            }
                        }
                    }
                    break;
                case FUNCTION_51:
@@ -315,36 +449,37 @@
                    int result = ProtocolParser51.parse(hexPacket);
                    int slot = slotAddress;
                    if (result == 1) {
//                        Dingshidialog.showTimedDialog(null, 5,slot+"号卡槽出卡成功请取走卡...");
                        SlotManager.changgehaska(slot, result);
                        SlotManager.changgehaska(slot, result);
                    } else {
                        String message=slot+"号卡槽取卡失败";
                        String message = slot + "号卡槽取卡失败";
                        Charulog.logOperation(message);
                    }
                    break;
                case FUNCTION_52:
                    //System.out.println("功能码 0x52 - LED亮度控制");
                    // LED亮度控制 - 无操作
                    break;
                case FUNCTION_80:
                    //System.out.println("功能码 0x80 - 工卡升级使能");
                    // 工卡升级使能 - 无操作
                    break;
                case FUNCTION_81:
                    //System.out.println("功能码 0x81 - 工作卡升级数据包");
                    // 工作卡升级数据包 - 无操作
                    break;
                case FUNCTION_82:
                    //System.out.println("功能码 0x82 - 单板升级使能");
                    // 单板升级使能 - 无操作
                    break;
                case FUNCTION_83:
                    //System.out.println("功能码 0x83 - 单板升级数据包");
                    // 单板升级数据包 - 无操作
                    break;
                default:
                    System.err.println("未知功能码: 0x" + Integer.toHexString(functionCode & 0xFF));
                    if (lunxun.DEBUG_ENABLED) {
                        System.err.println("未知功能码: 0x" + Integer.toHexString(functionCode & 0xFF));
                    }
                    break;
            }
            
        } catch (Exception e) {
            System.err.println("解析数据包时发生错误: " + e.getMessage());
            e.printStackTrace();
            // 不打印堆栈跟踪,避免产生大量日志对象
        }
    }
    
@@ -352,6 +487,10 @@
     * 优化的字节数组转十六进制字符串方法
     */
    private String bytesToHex(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return "";
        }
        hexBuilder.setLength(0); // 清空重用
        for (byte b : bytes) {
            hexBuilder.append(String.format("%02X", b));
@@ -390,12 +529,14 @@
     * 获取解析器状态信息
     */
    public String getStatusInfo() {
        return String.format("串口解析器状态: %s, 队列大小: %d/%d, 批量队列: %d/%d",
        return String.format("串口解析器状态: %s, 队列大小: %d/%d, 批量队列: %d/%d, 缓冲区: %d/%d",
                           isRunning ? "运行中" : "已停止", 
                           dataQueue.size(), 
                           dataQueue.remainingCapacity() + dataQueue.size(),
                           batchQueue.size(),
                           batchQueue.remainingCapacity() + batchQueue.size());
                           batchQueue.remainingCapacity() + batchQueue.size(),
                           bufferPosition,
                           dataBuffer.length);
    }
    
    /**
@@ -404,4 +545,14 @@
    public void setMaxRawDataPrintLength(int length) {
        // 实现根据需要调整
    }
    /**
     * 主动清理资源
     */
    public void cleanup() {
        stop();
        clearQueues();
        bufferPosition = 0;
        hexBuilder.setLength(0);
    }
}
src/xitongshezhi/kuaisuquka.java
@@ -140,12 +140,7 @@
            String hasCardStatus = slotInfo.getHasCard();
            String cardNumber = slotInfo.getCardNumber();
            
            // 调试单个卡槽
            if (i < 5) { // 只打印前5个卡槽的调试信息
                System.out.printf("刷新卡槽 %d: hasCard=%s, cardNumber=%s%n",
                    i + 1, hasCardStatus, cardNumber);
            }
            // 简化的判断逻辑 - 重点调试
            boolean reallyHasCard = false;