You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:06:36