ProcessBuilder waitFor()永远不会返回

时间:2017-09-20 21:03:52

标签: java

我试图将ProcessBuilder用于像“' ls”这样简单的事情。命令。我已经阅读了在waitFor()调用返回之前需要完成的流程流的问题,但即使将错误重定向到输出并消除了流,流程也永远不会返回。

public class ProcessTest {

    public static void main(String[] args) throws Exception {

        ProcessBuilder builder = new ProcessBuilder();
        builder.command("ls");

        builder.redirectErrorStream(true);

        Process process = builder.start();

        StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println);

        Executors.newSingleThreadExecutor().submit(streamGobbler);

        int exitCode = process.waitFor();
    }

}
与StreamGlobber一起成为一个天真的消费者:

    public class StreamGobbler implements Runnable {
    private InputStream inputStream;
    private Consumer<String> consumer;

    public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
        this.inputStream = inputStream;
        this.consumer = consumer;
    }

    @Override
    public void run() {
        new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer);
    }
}

有人能告诉我这里出了什么问题吗?

1 个答案:

答案 0 :(得分:0)

问题不在于处理外部流程,而是由ExecutorService返回的Executors.newSingleThreadExecutor()的错误使用。此方法创建在后台运行的线程,并且因为您永远不会关闭此执行程序(这将停止该线程),此线程会阻止JVM退出。

如果您愿意,可以通过添加打印出退出代码的行来证明ls进程退出。但请注意,此行可能不会出现在输出的底部。

要解决此问题,我们需要保留对已创建的ExecutorService的引用,然后在我们不再需要时将其关闭。尝试替换

        Executors.newSingleThreadExecutor().submit(streamGobbler);

        int exitCode = process.waitFor();

        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.submit(streamGobbler);

        int exitCode = process.waitFor();

        executor.shutdown();

我对你的代码做了这个改动,它从挂起到彻底退出。