2

私の Java アプリケーションでは、いくつかのスクリプトをサブプロセスとして実行し、Java からの stdout で出力を監視して、必要に応じて何らかの出力に対応できるようにする必要があります。

サブプロセスを生成し、実行されたスクリプトの stdout を入力ストリームにリダイレクトするために、apache commons-exec を使用しています。

私が抱えている問題は、ストリームから読み取るときに、サブプロセスの実行が完了するまで Java プロセスがブロックされることです。サブプロセスの最後まで出力に反応するのを待つことはできませんが、出力が利用可能になったら非同期で読み取る必要があります。

以下は私のJavaコードです:

public class SubProcessReact {
    public static class LogOutputStreamImpl extends LogOutputStream {

        @Override
        protected void processLine(String line, int logLevel) {
            System.out.println("R: " + line);
        }
    }

    public static void main (String[] args) throws IOException, InterruptedException {
        CommandLine cl = CommandLine.parse("python printNumbers.py");
        DefaultExecutor e = new DefaultExecutor();
        ExecuteStreamHandler sh = new PumpStreamHandler(new LogOutputStreamImpl());
        e.setStreamHandler(sh);

        Thread th = new Thread(() -> {
            try {
                e.execute(cl);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        });

        th.start();
    }
}

この例では、サブプロセスは python スクリプトであり、データが入ってくると Java コードが応答していることを確認できるように、出力間に 1 秒の遅延を加えてカウントアップします。

Python コード:

import time

for x in range(0,10):
    print x
    time.sleep(1)

LogOutputStreamImpl が各行を出力することを期待していますが、実際に起こっているのは、サブプロセスが完了するまでストリーム ブロックを読み取ってから、すべての出力を出力するということです。

これを意図したとおりに機能させるためにできることはありますか?

4

1 に答える 1

1

Java SE がすでにうまく行っていることを、なぜサード・パーティーのライブラリーを使って行うのでしょうか? 個人的には、プログラムを簡単に移植できるようにし、障害点を減らすために、依存する外部ライブラリをできるだけ少なくすることを好みます。

ProcessBuilder builder = new ProcessBuilder("python", "printNumbers.py");
builder.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
Process process = builder.start();

try (BufferedReader reader = new BufferedReader(
    new InputStreamReader(process.getInputStream()))) {

    reader.lines().forEach(line -> System.out.println("R: " + line));
}

process.waitFor();
于 2015-12-20T17:10:58.247 に答える