繁体   English   中英

Java Runtime.exec() -- 是否可以将流输出与wait()/notify() 同步?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM