我使用 Runtime.exec() 在 Java 中实现了一个简单的外部进程执行器。我已经实现了一个“stream gobbler”类,它消耗来自进程的输出流和错误流的进程输出。我的代码使用 Process.waitFor() 等待外部进程完成,然后我打印进程返回码。
我遇到的问题是进程在“stream gobblers”完成打印之前结束,因此在我的 Java 输出 (System.out) 中,返回的退出代码出现在进程输出/错误行的中间。
我的问题是,是否可以使用 wait()/notify() 来同步 System.out 上的输出,而不是在 while 循环中轮询每个 StreamGobbler 的活动状态?
这是代码:
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);
}
}
}