package chushihua; import xitongshezhi.Fkj; import xitongshezhi.SystemDebugDialog; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; /** * 在线轮询类 - 优化版本 * 专门用于定时轮询有卡的卡槽并发送查询指令 * 与原有的轮询查询类互补,专注于在线设备的持续监控 */ public class lunxunzaixian { private static final AtomicBoolean isRunning = new AtomicBoolean(false); private static final AtomicBoolean isPaused = new AtomicBoolean(false); private static final AtomicBoolean shouldStop = new AtomicBoolean(false); private static Thread onlinePollingThread; // 可配置的轮询参数(不再是final) private static int cycleInterval = 60000; // 完整轮询周期间隔:60秒 private static int slotInterval = 200; // 卡槽间查询间隔:200毫秒 // 卡槽相关常量 private static final int MIN_SLOT = 1; private static final int MAX_SLOT = 60; // 性能优化配置 private static final int BATCH_SIZE = 5; // 批量查询大小 private static int consecutiveFailures = 0; private static final int MAX_CONSECUTIVE_FAILURES = 3; /** * 启动在线轮询 - 优化版本 * @return true-启动成功, false-启动失败 */ public static boolean startOnlinePolling() { if (isRunning.get()) { SystemDebugDialog.appendAsciiData("Online polling is already in progress"); return true; } // 检查串口连接状态 if (!checkSerialConnectionWithRetry()) { System.err.println("串口未连接,无法启动在线轮询"); return false; } isRunning.set(true); isPaused.set(false); shouldStop.set(false); consecutiveFailures = 0; try { onlinePollingThread = new Thread(new OnlinePollingTask(), "Online-Polling-Thread"); onlinePollingThread.setDaemon(true); onlinePollingThread.start(); System.out.println("在线轮询已启动,周期间隔: " + cycleInterval + "ms, 卡槽间隔: " + slotInterval + "ms"); return true; } catch (Exception e) { System.err.println("启动在线轮询线程时发生异常: " + e.getMessage()); isRunning.set(false); shouldStop.set(true); return false; } } /** * 停止在线轮询 - 修复版本 * @return true-停止成功, false-停止失败 */ public static boolean stopOnlinePolling() { if (!isRunning.get()) { System.out.println("在线轮询未在运行"); return false; } shouldStop.set(true); isRunning.set(false); isPaused.set(false); if (onlinePollingThread != null) { onlinePollingThread.interrupt(); try { onlinePollingThread.join(3000); // 等待3秒 // 检查线程是否还在运行 if (onlinePollingThread.isAlive()) { System.err.println("在线轮询线程未在3秒内停止,标记为守护线程并忽略"); // 不强制停止,而是确保它是守护线程 onlinePollingThread.setDaemon(true); } } catch (InterruptedException e) { System.err.println("停止在线轮询时被中断: " + e.getMessage()); Thread.currentThread().interrupt(); } catch (Exception e) { System.err.println("停止在线轮询线程时发生异常: " + e.getMessage()); } finally { onlinePollingThread = null; } } shouldStop.set(false); System.out.println("在线轮询已停止"); return true; } /** * 暂停在线轮询 * @return true-暂停成功, false-暂停失败 */ public static boolean pauseOnlinePolling() { if (!isRunning.get()) { System.out.println("在线轮询未在运行,无法暂停"); return false; } if (isPaused.get()) { System.out.println("在线轮询已经处于暂停状态"); return false; } isPaused.set(true); System.out.println("在线轮询已暂停"); return true; } /** * 恢复在线轮询 * @return true-恢复成功, false-恢复失败 */ public static boolean resumeOnlinePolling() { if (!isRunning.get()) { System.out.println("在线轮询未在运行,无法恢复"); return false; } if (!isPaused.get()) { System.out.println("在线轮询未处于暂停状态"); return false; } // 恢复前检查串口连接 if (!checkSerialConnectionWithRetry()) { System.err.println("串口未连接,无法恢复在线轮询"); return false; } isPaused.set(false); synchronized (lunxunzaixian.class) { lunxunzaixian.class.notifyAll(); // 唤醒等待的线程 } System.out.println("在线轮询已恢复"); return true; } /** * 检查在线轮询状态 * @return true-正在运行, false-已停止 */ public static boolean isOnlinePolling() { return isRunning.get(); } /** * 检查是否暂停 * @return true-已暂停, false-未暂停 */ public static boolean isOnlinePaused() { return isPaused.get(); } /** * 重新启动在线轮询 * @return true-重启成功, false-重启失败 */ public static boolean restartOnlinePolling() { stopOnlinePolling(); // 等待一小段时间确保线程完全停止 try { Thread.sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return startOnlinePolling(); } /** * 设置轮询间隔参数 * @param cycleMs 完整轮询周期间隔(毫秒) * @param slotMs 卡槽间查询间隔(毫秒) */ public static void setPollingIntervals(int cycleMs, int slotMs) { cycleInterval = Math.max(cycleMs, 1000); // 最小1秒 slotInterval = Math.max(slotMs, 50); // 最小50毫秒 System.out.println("在线轮询间隔已设置 - 周期间隔: " + cycleInterval + "ms, 卡槽间隔: " + slotInterval + "ms"); // 如果正在运行,重新启动以应用新的间隔 if (isRunning.get()) { restartOnlinePolling(); } } /** * 获取当前轮询间隔配置 * @return 间隔配置字符串 */ public static String getPollingIntervals() { return String.format("周期间隔: %dms, 卡槽间隔: %dms", cycleInterval, slotInterval); } /** * 获取在线轮询统计信息 * @return 统计信息字符串 */ public static String getOnlinePollingStats() { int totalSlots = MAX_SLOT - MIN_SLOT + 1; int cardSlots = countCardSlots(); String status; if (!isRunning.get()) { status = "已停止"; } else if (isPaused.get()) { status = "已暂停"; } else { status = "运行中"; } return String.format("在线轮询状态: %s, 有卡卡槽: %d/%d, 周期间隔: %ds, 卡槽间隔: %dms", status, cardSlots, totalSlots, cycleInterval/1000, slotInterval); } /** * 统计有卡的卡槽数量 * @return 有卡的卡槽数量 */ private static int countCardSlots() { if (SlotManager.slotArray == null) { return 0; } int count = 0; for (Fkj slot : SlotManager.slotArray) { if (slot != null && "1".equals(slot.getHasCard())) { count++; } } return count; } /** * 带重试的串口连接检查 */ private static boolean checkSerialConnectionWithRetry() { for (int i = 0; i < 3; i++) { if (lunxun.checkSerialConnection()) { return true; } try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } } return false; } /** * 在线轮询任务内部类 - 优化版本 * 专门轮询有卡的卡槽,优化资源使用 */ private static class OnlinePollingTask implements Runnable { @Override public void run() { System.out.println("在线轮询线程开始运行"); while (isRunning.get() && !Thread.currentThread().isInterrupted() && !shouldStop.get()) { try { // 检查是否暂停 if (isPaused.get()) { synchronized (lunxunzaixian.class) { while (isPaused.get() && isRunning.get() && !shouldStop.get()) { lunxunzaixian.class.wait(1000); // 等待1秒或直到被唤醒 } } continue; } // 检查串口连接状态 if (!checkSerialConnectionWithRetry()) { System.err.println("串口连接断开,暂停在线轮询"); pauseOnlinePolling(); continue; } // 执行一轮有卡卡槽的轮询 if (pollCardSlotsOptimized()) { consecutiveFailures = 0; // 重置连续失败计数 } else { consecutiveFailures++; if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) { System.err.println("连续失败次数过多,暂停在线轮询"); pauseOnlinePolling(); } } // 等待完整周期间隔 Thread.sleep(cycleInterval); } catch (InterruptedException e) { System.out.println("在线轮询线程被中断"); Thread.currentThread().interrupt(); break; } catch (Exception e) { System.err.println("在线轮询过程中发生异常: " + e.getMessage()); consecutiveFailures++; // 发生异常时等待一段时间再继续 try { Thread.sleep(5000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } } System.out.println("在线轮询线程结束运行"); } /** * 优化版本:批量轮询有卡卡槽 * @return true-轮询成功, false-轮询失败 */ private boolean pollCardSlotsOptimized() { if (SlotManager.slotArray == null) { System.err.println("卡槽数组未初始化"); return false; } List cardSlots = new ArrayList<>(); // 第一阶段:收集所有有卡卡槽 for (int i = 0; i < SlotManager.slotArray.length; i++) { if (!isRunning.get() || Thread.currentThread().isInterrupted() || shouldStop.get()) { break; } Fkj slot = SlotManager.slotArray[i]; if (slot != null && "1".equals(slot.getHasCard())) { cardSlots.add(i + 1); } } if (cardSlots.isEmpty()) { if (lunxun.DEBUG_ENABLED) { System.out.println("没有找到有卡的卡槽"); } return true; } int polledCount = 0; int totalCardSlots = cardSlots.size(); // 第二阶段:批量查询有卡卡槽 for (int i = 0; i < cardSlots.size(); i += BATCH_SIZE) { if (!isRunning.get() || Thread.currentThread().isInterrupted() || shouldStop.get()) { break; } int end = Math.min(i + BATCH_SIZE, cardSlots.size()); List batch = cardSlots.subList(i, end); // 批次内查询 for (int slotNumber : batch) { if (sendQueryToCardSlot(slotNumber)) { polledCount++; } } // 批次间间隔 if (end < cardSlots.size()) { try { Thread.sleep(slotInterval * BATCH_SIZE); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } } if (polledCount > 0 && lunxun.DEBUG_ENABLED) { System.out.println("在线轮询完成,成功查询 " + polledCount + "/" + totalCardSlots + " 个有卡卡槽"); } return polledCount > 0; } /** * 向指定有卡卡槽发送查询指令 * @param slotNumber 卡槽编号 * @return true-发送成功, false-发送失败 */ private boolean sendQueryToCardSlot(int slotNumber) { try { // 使用原有的立即查询功能 boolean result = lunxun.sendImmediateQuery(slotNumber); if (result) { // 记录调试信息(减少输出频率) if (lunxun.DEBUG_ENABLED && (slotNumber == 1 || slotNumber % 10 == 0)) { System.out.println("在线轮询 - 查询有卡卡槽 " + slotNumber); } return true; } else { System.err.println("在线轮询 - 查询有卡卡槽 " + slotNumber + " 失败"); return false; } } catch (Exception e) { System.err.println("在线轮询 - 查询有卡卡槽 " + slotNumber + " 时发生异常: " + e.getMessage()); return false; } } } /** * 手动触发立即轮询(不等待周期)- 优化版本 * @return 成功查询的卡槽数量 */ public static int triggerImmediatePolling() { if (!isRunning.get() || isPaused.get()) { System.err.println("在线轮询未运行或已暂停,无法立即轮询"); return 0; } if (!checkSerialConnectionWithRetry()) { System.err.println("串口未连接,无法执行立即轮询"); return 0; } System.out.println("开始立即轮询有卡卡槽..."); OnlinePollingTask task = new OnlinePollingTask(); // 使用新的批量轮询方法 int cardSlotCount = countCardSlots(); // 在新线程中执行立即轮询,避免阻塞当前线程 Thread immediateThread = new Thread(() -> { try { task.pollCardSlotsOptimized(); } catch (Exception e) { System.err.println("立即轮询过程中发生异常: " + e.getMessage()); } }, "Immediate-Online-Polling"); immediateThread.setDaemon(true); immediateThread.start(); return cardSlotCount; } /** * 设置在线轮询暂停状态(供其他类调用) * @param paused true-暂停轮询, false-恢复轮询 * @return true-设置成功, false-设置失败 */ public static boolean setOnlinePollingPaused(boolean paused) { if (!isRunning.get()) { System.out.println("在线轮询未在运行,无法设置暂停状态"); return false; } if (paused) { return pauseOnlinePolling(); } else { return resumeOnlinePolling(); } } /** * 获取性能统计信息 */ public static String getPerformanceStats() { return String.format("批量大小: %d, 周期间隔: %dms, 卡槽间隔: %dms", BATCH_SIZE, cycleInterval, slotInterval); } }