Java process.waitFor(time,unit)不会超时

时间:2019-06-24 09:36:14

标签: java

在我的Java 11(Debian下为openjdk 11.0.3 2019-04-16)程序中,我使用ProcessBuilder启动外部命令。外部命令可能会挂起,因此我需要它在给定的时间后超时。

所以我用p.waitFor(time, unit)应该返回

  

如果进程已退出,则为true;如果进程已退出,则等待时间为false。

        ProcessBuilder pb = new ProcessBuilder(externalCommand);

        // Merges the error stream with the standard output stream
        pb.redirectErrorStream(true);

        Process p = pb.start();

        Date start = new Date();

        BufferedReader br = new BufferedReader(new InputStreamReader(
                p.getInputStream()));

        String tempLine;

        /**
         * We only want the first 10 lines otherwise it will print thousands of
         * useless lines (always the same)
         */
        int nbOfLinesInlogs = 10;

        while ((tempLine = br.readLine()) != null) {

            // We only report errors to the user
            if (tempLine.toLowerCase().startsWith("error") && nbOfLinesInlogs > 0) {
                Level level = Level.WARNING;


                System.err.println("External command output : " + tempLine);
                // There was an error
                errorDetected = true;

                nbOfLinesInlogs--;
            }

        }


        if (p.waitFor(10l,
                TimeUnit.NANOSECONDS)) {

            long elapsedInMillis = new Date().getTime() - start.getTime();
            System.err.println("External process succeeded and took " + elapsedInMillis + " ms");
            // prints Externalprocess succeeded and took 15327 ms
            ...
         }
         else {
            System.err.println("External process timed out");
            // This is never printed!
            throw new InterruptedException(
                    "External process timed out!");
         } 

但是该过程永远不会超时并打印花费了15 s,尽管它应该在10 ns后超时(这只是一项检查超时是否按预期工作的测试)。我还尝试了µs,ms和s,结果相同。

如何使进程超时时返回假?

任何帮助表示赞赏,

1 个答案:

答案 0 :(得分:0)

感谢您的评论。根据上面的评论,一种解决方案是删除流程启动和流程等待流程(1.0.0)之间的代码段

waitFor(...)

原因是(请参阅@TreffnonX评论)

  

因为我使用了while循环,一旦输入关闭,它只会返回false。由于我的输入仅在流程终止时关闭,因此我的检查(waitFor)在流程结束后进行。

另一个解决方案可能是启动一个单独的线程,该线程将在while循环中运行。