Java线程问题 - 监听n个错误流

时间:2009-08-05 21:04:14

标签: java multithreading

首先我要说的是我的线程经验非常低。

我有一个应用程序通过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

2 个答案:

答案 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()

即。启动每个进程,并立即开始在单独的线程中使用每个进程的输出。消耗线程启动后,只需等待每个进程完成并返回。