首先我要说的是我的线程经验非常低。
我有一个应用程序通过Runtime.exec
方法启动其他几个Java jar。问题是启动的jar需要同时运行,但是为了获得启动的jar的错误流,你必须基本上有一个循环'坐着和听',直到过程完成。
这就是我现在所拥有的:
_processes.add( Runtime.getRuntime().exec( commandList.toArray( new String[ commandList.size() ] ) ) );
Thread thread = new Thread( new Runnable() {
private final int _processNumber = _processes.size() - 1;
public void run() {
String streamData = _processNumber + " : ";
streamData += "StdError [\r";
BufferedReader bufferedReader =
new BufferedReader( new InputStreamReader( _processes.get( _processNumber ).getErrorStream() ) );
String line = null;
try {
while ( ( line = bufferedReader.readLine() ) != null ) {
streamData += line + "\r";
}
bufferedReader.close();
streamData += "]\r";
LOG.error( streamData );
}
catch ( Exception exception ) {
LOG.fatal( exception.getMessage() );
exception.printStackTrace();
}
}
} );
thread.start();
任何人都可以解释如何让“错误流监听器线程”正常工作吗?
TIA
答案 0 :(得分:1)
不使用Runtime.getRuntime()。exec(),而是使用Process来启动外部进程..它会让你的生活变得更轻松..
我的项目的示例代码:
//Build command
List<String> commands = new ArrayList<String>();
commands.add("my_application");
commands.add("arg1");
commands.add("arg2");
log.debug("{}", commands);
//Run command with arguments
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(directory);
pb.redirectErrorStream(true);
Process process = pb.start();
//Read output
StringBuilder out = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader
(process.getInputStream()));
//Only log unique lines (you might not need this)
String line = null, previous = null;
while ((line = br.readLine()) != null)
if (!line.equals(previous)) {
previous = line;
out.append(line).append('\n');
log.debug(line);
}
//Check result
if (process.waitFor() == 0)
return 0;
//Abnormal termination: Log command parameters and output and throw ExecutionException
log.error("{}", commands);
log.error("\n{}", out.toString());
throw new ExecutionException(new IllegalStateException("MyApplication exit code 1"));
答案 1 :(得分:0)
有关如何使用Runtime.exec()的非常好的教程here。仔细阅读所有内容,但请特别注意第4页,其中介绍了如何使用在单独线程中运行的“StreamGobbler”来使用正在执行的进程中的std out和std err流。
基本上,您应该在pseduo代码中实现的目标是:
Runtime rt1 = Runtime.getRuntime().exec("my command")
new StreamGobbler(rt1.getOutputStream()).start()
new StreamGobbler(rt1.getErrorStream()).start()
//repeat for each external process (rt2, rt3 etc)
...
rt1.waitFor()
rt2.waitFor()
rt3.waitFor()
即。启动每个进程,并立即开始在单独的线程中使用每个进程的输出。消耗线程启动后,只需等待每个进程完成并返回。