Servlet中通过while循环实现函数重复调用检测窗口状态
我来帮你解决这个循环检测窗口关闭的问题,先梳理下现有代码里的问题,再给出优化后的实现方案:
解决循环检测Admin窗口关闭的问题
1. 先修复getWin()函数的逻辑缺陷
你的getWin()存在一个关键问题:会用最后一行的检测结果覆盖之前的判断——比如如果tasklist输出里前面有包含PID的行(说明窗口存在),但最后一行没有,test会被错误地设为0,导致误判。另外,函数没有正确清理资源,也没处理进程错误流,可能引发阻塞或资源泄漏。
修正后的getWin():
private int getWin() { int test = 0; // 默认窗口不存在 Process checkProcess = null; BufferedReader inputReader = null; BufferedReader errorReader = null; try { String checkCommand = "cmd /c tasklist /V /FI \"WINDOWTITLE eq Admin:*\""; checkProcess = Runtime.getRuntime().exec(checkCommand); // 同时处理输入流和错误流,避免进程阻塞 inputReader = new BufferedReader(new InputStreamReader(checkProcess.getInputStream())); errorReader = new BufferedReader(new InputStreamReader(checkProcess.getErrorStream())); String checkLine; String checkVal = "PID"; // 只要找到包含PID的行,就说明窗口存在,直接终止循环 while ((checkLine = inputReader.readLine()) != null) { if (checkLine.contains(checkVal)) { test = 1; break; } } // 读取错误流内容(可选,用于调试) while ((checkLine = errorReader.readLine()) != null) { System.err.println("tasklist错误输出: " + checkLine); } checkProcess.waitFor(); // 等待命令执行完成 } catch (IOException | InterruptedException e) { e.printStackTrace(); } finally { // 强制清理所有资源 try { if (inputReader != null) inputReader.close(); if (errorReader != null) errorReader.close(); if (checkProcess != null) checkProcess.destroy(); } catch (IOException e) { e.printStackTrace(); } } return test; }
2. 实现高效的循环检测逻辑
原循环没有任何延迟,会持续占用CPU资源,而且依赖类成员变量test在Servlet多线程环境下有线程安全风险。我们直接用getWin()的返回值控制循环,同时添加短暂休眠降低系统消耗:
修改performTask里的循环部分:
if (exitCode == 0) { System.out.println("命令执行成功"); // 循环检测窗口,直到窗口关闭(getWin()返回0) while (getWin() == 1) { try { TimeUnit.SECONDS.sleep(1); // 每隔1秒检测一次,可根据需求调整间隔 } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("检测线程被中断,停止检测"); break; } } // 执行窗口关闭命令(如果需要,循环已经确认窗口关闭的话也可以省略这一步) Process endProcess; String endCommands = "taskkill /F /FI \"WINDOWTITLE eq Admin:*\""; endProcess = Runtime.getRuntime().exec(endCommands); int exitCodeEnd = endProcess.waitFor(); System.out.println("窗口关闭命令退出码: " + exitCodeEnd); // 后续的文件读取和页面转发逻辑... }
3. 额外优化建议
- 移除类成员变量:原代码中的
is、test、retval都是类成员,在Servlet多线程环境下会导致数据混乱,建议全部改为方法内的局部变量。 - 增加超时机制:可以给循环加一个超时时间,避免无限等待,比如最多等待5分钟:
long startTime = System.currentTimeMillis(); long timeout = 5 * 60 * 1000; // 5分钟超时 while (getWin() == 1) { if (System.currentTimeMillis() - startTime > timeout) { System.err.println("窗口关闭检测超时"); break; } TimeUnit.SECONDS.sleep(1); }
这样修改后,就能稳定实现持续检测窗口状态,直到窗口关闭,同时不会过度消耗系统资源。
内容的提问来源于stack exchange,提问作者Viking
相关产品推荐
相关产品推荐

