From d22349714c8d199c02f336f90fba841ef8f5cd39 Mon Sep 17 00:00:00 2001
From: 张世豪 <979909237@qq.com>
Date: 星期五, 21 十一月 2025 17:46:23 +0800
Subject: [PATCH] 优化内存后最终版202511211746
---
src/publicway/ProtocolParser01.java | 371 +++++++++++++++++++++++-----------------------------
1 files changed, 167 insertions(+), 204 deletions(-)
diff --git a/src/publicway/ProtocolParser01.java b/src/publicway/ProtocolParser01.java
index 3b402aa..2a2d4f0 100644
--- a/src/publicway/ProtocolParser01.java
+++ b/src/publicway/ProtocolParser01.java
@@ -1,13 +1,20 @@
package publicway;
import java.util.ArrayList;
import java.util.List;
-
-import chuankou.SerialPortService;
import chushihua.SlotManager;
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) {
@@ -19,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()) {
@@ -69,6 +80,7 @@
throw new IllegalArgumentException("非DDCC协议数据");
}
+ ParseResult result = ParseResultPool.borrowObject();
try {
// 1. 移除包头DDCC进行解析
String dataWithoutHeader = hexData.substring(4);
@@ -79,178 +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之前的数据
- */
- 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) {
- System.err.println("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;
}
@@ -258,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, "待机"),
@@ -288,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()) {
@@ -306,9 +295,6 @@
}
}
- /**
- * 门状态枚举
- */
public enum DoorStatus {
UNKNOWN(0, "未知状态"),
DOOR_OPEN(1, "开门状态"),
@@ -322,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()) {
@@ -340,9 +321,6 @@
}
}
- /**
- * 卡状态枚举
- */
public enum CardStatus {
NO_CARD(0, "无卡"),
HAS_CARD(1, "有卡"),
@@ -357,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()) {
@@ -375,9 +348,6 @@
}
}
- /**
- * 故障类型枚举
- */
public enum FaultType {
INSERT_ERROR(0x01, "插卡错误"),
OVER_CURRENT(0x02, "过流"),
@@ -393,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;
@@ -418,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,
@@ -452,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方法
@@ -475,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());
@@ -499,49 +456,47 @@
@Override
public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("=== DDCC协议数据解析结果 ===\n");
- sb.append("1. 主机地址: ").append(String.format("%02X", hostAddress));
- sb.append("2. 卡槽编号: ").append(slotNumber);
- sb.append("3. 工作状态: ").append(workStatus.getDescription())
- .append(" (").append(workStatus.getValue());
- sb.append("4. 门状态: ").append(doorStatus.getDescription())
- .append(" (").append(doorStatus.getValue());
- sb.append("5. 卡状态: ").append(cardStatus.getDescription())
- .append(" (").append(cardStatus.getValue());
- sb.append("6. 卡状态变更: ").append(cardStatusChange);
- sb.append("7. 卡号: ").append(cardNumber);
- 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();
+ 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())
+ .append("(").append(workStatus.getValue()).append(")");
+ sb.append("4. 门状态:").append(doorStatus.getDescription())
+ .append("(").append(doorStatus.getValue()).append(")");
+ sb.append("5.卡状态:").append(cardStatus.getDescription())
+ .append("(").append(cardStatus.getValue()).append(")");
+ sb.append("6.卡状态变更:").append(cardStatusChange);
+ sb.append("7.卡号:").append(cardNumber);
+ 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(" 字节");
+
+ 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 {
// 预创建对象
@@ -556,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();
+ }
}
}
\ No newline at end of file
--
Gitblit v1.9.3