3

我使用 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);
        }
    }

}
4

2 回答 2

2

在您的主线程中,除了执行 waitFor() 来完成子进程,还执行 errorGobbler.join() 和 outputGobbler.join(),然后您将不需要 while(xGobbler.isAlive())。

于 2012-12-01T11:12:34.250 回答
1

首先,您应该调用join()您启动的任何线程。

其次,System.out是缓冲的,所以这可以解释它。System.out.flush()在阅读内容之前尝试调用。

了解这是否是缓冲问题的一种方法是暂时将调用的进程更改为写入System.err而不是System.out. System.err没有缓冲。

于 2012-12-01T02:15:42.523 回答