Java Runtime.exec()--是否可以将流输出与wait()/notify()同步?
我使用Runtime.exec()在Java中实现了一个简单的外部进程执行器。我已经实现了一个“streamgobbler”类,它使用来自进程的输出流和错误流的进程输出。我的代码使用process.waitFor()等待外部进程完成,然后打印进程返回代码Java Runtime.exec()--是否可以将流输出与wait()/notify()同步?,java,multithreading,process,stream,runtime,Java,Multithreading,Process,Stream,Runtime,我使用Runtime.exec()在Java中实现了一个简单的外部进程执行器。我已经实现了一个“streamgobbler”类,它使用来自进程的输出流和错误流的进程输出。我的代码使用process.waitFor()等待外部进程完成,然后打印进程返回代码 我所遇到的问题是,在“流GbBLBER”完成打印之前,该过程结束,因此在java输出(System .out)中,返回的退出代码出现在进程输出/错误行的中间。 我的问题是,是否可以使用wait()/notify()同步System.out上的输
我所遇到的问题是,在“流GbBLBER”完成打印之前,该过程结束,因此在java输出(System .out)中,返回的退出代码出现在进程输出/错误行的中间。 我的问题是,是否可以使用wait()/notify()同步System.out上的输出,而不是在while循环中轮询每个StreamGoBler的活动状态
代码如下: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);
}
}
}
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.InputStreamReader;
公共类RuntimeExecExample
{
私有枚举流类型
{
产出,
错误
}
公共类MyStreamGobbler扩展线程
{
私有输入流是;
流线型;
public MyStreamGobbler(InputStream为,StreamType)
{
this.is=is;
this.type=type;
}
公开募捐
{
尝试
{
BufferedReader br=新的BufferedReader(新的InputStreamReader(is));
字符串行=null;
而((line=br.readLine())!=null)
{
System.out.println(type.toString()+“>”+行);
}
}
捕获(ioe异常ioe)
{
ioe.printStackTrace();
}
}
}
public void executeCommand(字符串参数[])
{
尝试
{
Runtime rt=Runtime.getRuntime();
字符串命令行=”;
用于(字符串cmdItem:args)
{
命令行+=“”+cmdItem;
}
System.out.println(“执行”+命令行);
进程进程=rt.exec(args);
//有错误信息吗?
MyStreamGobbler errorGobbler=新的MyStreamGobbler(proc.getErrorStream(),StreamType.ERROR);
//有输出吗?
MyStreamGobbler outputGobbler=新的MyStreamGobbler(proc.getInputStream(),StreamType.OUTPUT);
//把他们踢出去
errorGobbler.start();
outputGobbler.start();
//有错误吗???
int exitVal=proc.waitFor();
/*
*在打印退出值之前,请等待两者都完成
*有没有办法用wait()/notify()实现这一点??
*/
while(errorGobbler.isAlive())
;
while(outputGobbler.isAlive())
;
System.out.println(“ExitValue:+exitVal”);
}
捕获(可丢弃的t)
{
t、 printStackTrace();
}
}
公共静态void main(字符串参数[])
{
如果(参数长度<1)
{
println(“用法:java RuntimeExecExample[…]”;
系统出口(1);
}
其他的
{
RuntimeExecExample RuntimeExecExample=新的RuntimeExecExample();
runtimeExecExample.executeCommand(args);
}
}
}
首先,您应该在启动的任何线程上调用join()
其次,System.out
是缓冲的,这可能解释了这一点。在阅读内容之前,请尝试调用System.out.flush()
了解这是否是缓冲问题的一种方法是临时将调用的进程更改为写入
System.err
,而不是System.out
System.err
未被缓冲。在主线程中,除了执行waitFor()子进程以完成外,还要执行errorGobbler.join()和outputGobbler.join(),这样就不需要while(xGobbler.isAlive()).为什么不使用倒计时锁存器?为什么要在单独的线程中运行gobbler?@EvgeniyDorofeev:gobbler应该在单独的线程中运行。因此,我想到的第一个解决方法是在两个列表实例中收集输出(两个流),然后在外部进程结束时,将这两者和退出代码打印到System.out。这个解决方案似乎很极端,我想知道是否可以等待线程结束。我认为System.err也被缓冲了。请参阅系统src:setErr0(新打印流(新缓冲输出流(fdErr,128),true));你应该为此感到高兴。标准错误流不应该被缓冲。不过这很奇怪。我似乎回忆起SystemErr刷新要比SystemOut.System.err.println(“111111”)快得多;System.out.println(“2222222”);总是在Eclipse中打印222221111(在我的电脑上)。但从cmd行看,这可能是因为Eclipse注入了自己的System.out
和System.err
,所以它可以在控制台视图中显示输出。这就是我想要的。谢谢