Java进程:单线程读取子进程的stdout和stderr

Java Process: read stdout and stderr of a subprocess in a single thread

假设我在 Java 中启动了一个子进程,它可能会写入 stdout 和 stderr:

Process subprocess = Runtime.getRuntime().exec(…);

我想阅读它所有的标准输出和标准错误;或者干脆忽略它们。

  1. 如果我这样做:

    readAllFrom(subprocess.getInputStream()); //stdout is getInputStream, weird!
    readAllFrom(subprocess.getErrorStream()); //stderr
    

    …如果子进程首先尝试将数据输出到 stderr 并因此在该点阻塞,它会卡住。

    如果我这样做:

    while (…) {
        readLineFrom(subprocess.getInputStream());
        readLineFrom(subprocess.getErrorStream());
    }
    

    ……其实风险好像是一样的

  2. 如果我这样做:

    while (…) {
        nonblockingReadFrom(subprocess.getInputStream());
        nonblockingReadFrom(subprocess.getOutputStream());
    }
    

    其中 nonblockingReadFrom 可以是这样的:

    … nonblockingReadFrom(InputStream stream) {
        byte[] buffer = new byte[…];
        stream.read(buffer, 0, Math.min(stream.available(), buffer.length));
        …
    }
    

    …如果子进程输出数据有一些暂停,它将产生无用的 100%-CPU-负载。

  3. 当然,我可以创建单独的线程。像这里这样的东西(需要1, 2). But my question is about doing all in the same thread. Probably, something like Java interface to select system call

所以,问题是:是否可以在不使用额外线程或临时文件的情况下正确处理 Java 中 java.lang.Process 类型的子进程的标准输出和标准错误?

不,您不能只从 Process 返回的 InputStream 创建 SelectableChannel,这是 Java api 的限制 AFAICT .