【问题标题】:Closing process causes high cpu usage in input.readLine()关闭进程导致 input.readLine() 中 CPU 使用率高
【发布时间】:2020-07-13 14:00:35
【问题描述】:

我有使用 ProcessBuilder 运行 cmd.exe 进程的代码,当我使用 process.destroy(); CPU 使用率增加(0% > 30%)。每次我启动并销毁 cmd.exe 时,都会出现导致 CPU 使用率高达 100% 的新线程。当 InputStream 结束时,我能以某种方式停止这个循环吗?当服务器以 Ctrl-C 停止并且客户端具有高 CPU 使用率时,在我的另一个应用程序中也是如此。

input.readLine(); 想从不存在的 InputStream 中读取,导致 CPU 使用率过高。卡在这一行了。

我使用 Java 8

代码:

InputStream inputraw = process.getInputStream();
BufferedReader input = new BufferedReader(new InputStreamReader(inputraw));
while(true)    
{
    String cmd = input.readLine(); //HERE!
    //write cmd to console functions.....
}
if (isWindows) {
    command = (String.format("cmd.exe"));
} else {
    command = (String.format("sh"));
}
ProcessBuilder pb = new ProcessBuilder()
    .command(command)
    .redirectErrorStream(true);
process = pb.start();

【问题讨论】:

  • (String.format("cmd.exe")) 而不仅仅是写"cmd.exe" 的目的是什么?除此之外,如果不是您正在积极创建的线程,那么会出现什么样的“新线程”?
  • 这只是我的代码的一部分。 String.format("cmd.exe") 之前在这里运行 String.format("cmd.exe /c %s",cmd)。
  • String.format("cmd.exe /c %s",cmd) 仍然是一种不必要的复杂和低效的表达方式"cmd.exe /c %s" + cmd。但无论如何,关键是你提到但没有提供相关信息的新线程。
  • @Holger 线程不是问题我已经通过在线程中创建 input.readLine 并在我的服务器应用程序超时后将其终止来临时修复它。问题是代码卡在 input.readline() 上。在调试器中代码卡在这里
  • 然后,我建议删除“新线程出现”这个误导性短语。我以前见过这种现象,FileInputStream 在尝试从损坏的管道中读取时会使用 100% CPU(在一个核心上)。我会避免使用BufferedReader.readLine() 并使用inputStream.read(byteArray, 0, (int)Math.min(inputStream.available(), byteArray.length())) 来避免任何阻塞读取并稍后进行处理(转换为字符串,拆分为行)。但是,当您对输出所做的只是将其写入控制台时,请改用ProcessBuilder 上的redirectOutput(ProcessBuilder.Redirect.INHERIT)

标签: java multithreading input process


【解决方案1】:

我已经找到了解决这个问题的方法:

(如果您想发布更好的答案,您仍然可以这样做)

    public static String readLine(InputStream s) throws Exception {
        String cmd = "";
        try {
            int ch = s.read();
            cmd += (char) ch;
            StringBuilder cmdBuilder = new StringBuilder(cmd);
            while (ch != 10 && ch >= 0) {
                ch = s.read();
                if (ch == 10 || ch < 0) break;
                cmdBuilder.append((char) ch);
            }
            cmd = cmdBuilder.toString();
        } catch (Exception ex) {
            throw new Exception("Input was empty!");
        }
        return cmd;
    }

【讨论】:

    猜你喜欢
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    相关资源
    最近更新 更多