Runtime.exec()を使用して、Javaで単純な外部プロセスエグゼキュータを実装しました。プロセスの出力ストリームとエラーストリームからのプロセス出力を消費する「streamgobbler」クラスを実装しました。私のコードは、Process.waitFor()を使用して外部プロセスが完了するのを待ってから、プロセスのリターンコードを出力します。
私が経験している問題は、「ストリームゴブラー」が印刷を完了する前にプロセスが終了することです。そのため、Java出力(System.out)では、返された終了コードがプロセス出力/エラー行の中央に表示されます。
私の質問は、whileループで各StreamGobblerのアライブステータスをポーリングする代わりに、wait()/ notify()を使用してSystem.outの出力を同期することは可能ですか?
コードは次のとおりです。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class RuntimeExecExample
{
private enum StreamType
{
OUTPUT,
ERROR
}
public class MyStreamGobbler extends Thread
{
private InputStream is;
StreamType type;
public MyStreamGobbler(InputStream is, StreamType type)
{
this.is = is;
this.type = type;
}
public void run()
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line=null;
while ( (line = br.readLine()) != null)
{
System.out.println(type.toString() + ">" + line);
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
public void executeCommand(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
String commandLine = "";
for(String cmdItem : args)
{
commandLine += " " + cmdItem;
}
System.out.println("Exec-ing " + commandLine);
Process proc = rt.exec(args);
// any error message?
MyStreamGobbler errorGobbler = new MyStreamGobbler(proc.getErrorStream(), StreamType.ERROR);
// any output?
MyStreamGobbler outputGobbler = new MyStreamGobbler(proc.getInputStream(), StreamType.OUTPUT);
// kick them off
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
/*
* Wait for both to finish before printing exit value
* IS THERE A WAY TO DO THIS WITH wait()/notify() ??
*/
while(errorGobbler.isAlive())
;
while(outputGobbler.isAlive())
;
System.out.println("ExitValue: " + exitVal);
}
catch (Throwable t)
{
t.printStackTrace();
}
}
public static void main(String args[])
{
if(args.length < 1)
{
System.out.println("USAGE: java RuntimeExecExample <cmd> [<arg1> <arg2> ..]");
System.exit(1);
}
else
{
RuntimeExecExample runtimeExecExample = new RuntimeExecExample();
runtimeExecExample.executeCommand(args);
}
}
}