[英]Java Runtime.exec() -- Is it possible to synchronize stream output with wait()/notify()?
我已经使用 Runtime.exec() 在 Java 中实现了一个简单的外部进程执行器。 我已经实现了一个“stream gobbler”类,它消耗来自进程输出流和错误流的进程输出。 我的代码使用 Process.waitFor() 等待外部进程完成,然后打印进程返回代码。
我遇到的问题是进程在“流吞没器”完成打印之前结束,因此在我的 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);
}
}
}
在您的主线程中,除了执行waitFor() 子进程以完成之外,还执行errorGobbler.join() 和outputGobbler.join(),那么您将不需要while(xGobbler.isAlive())。
首先,您应该在您启动的任何线程上调用join()
。
其次, System.out
是缓冲的,所以这可以解释它。 在阅读内容之前尝试调用System.out.flush()
。
了解这是否是缓冲问题的一种方法是临时更改您调用的进程以写入System.err
而不是System.out
。 System.err
没有缓冲。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.