Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Runtime.exec()生成的进程的高效执行和输出流重定向_Java_Multithreading_Performance_Stream_Runtime.exec - Fatal编程技术网

Java 使用Runtime.exec()生成的进程的高效执行和输出流重定向

Java 使用Runtime.exec()生成的进程的高效执行和输出流重定向,java,multithreading,performance,stream,runtime.exec,Java,Multithreading,Performance,Stream,Runtime.exec,我有一个脚本,它可以多次执行一个程序,为STDERR和STDOUT生成大约350行输出。现在,我需要用Java执行脚本,从而将输出流打印到其原始目的地。因此,基本上,我从Java类内部执行脚本,保持用户的原始行为 我这样做的灵感来自于这样的建议,从功能上来说,效果很好 Process p = Runtime.getRuntime().exec(cmdarray); new Thread(new ProcessInputStreamHandler(p.getInputStream(), Syste

我有一个脚本,它可以多次执行一个程序,为STDERR和STDOUT生成大约350行输出。现在,我需要用Java执行脚本,从而将输出流打印到其原始目的地。因此,基本上,我从Java类内部执行脚本,保持用户的原始行为

我这样做的灵感来自于这样的建议,从功能上来说,效果很好

Process p = Runtime.getRuntime().exec(cmdarray);
new Thread(new ProcessInputStreamHandler(p.getInputStream(), System.out)).start();
new Thread(new ProcessInputStreamHandler(p.getErrorStream(), System.err)).start();
return p.waitFor();
ProcessInputStreamHandler

class ProcessInputStreamHandler implements Runnable {
    private BufferedReader in_reader;
    private PrintStream out_stream;

    public ProcessInputStreamHandler(final InputStream in_stream, final PrintStream out_stream) {
        this.in_reader  = new BufferedReader(new InputStreamReader(in_stream));
        this.out_stream = out_stream;
    }

    @Override public void run() {
        String line;
        try {
            while ((line = in_reader.readLine()) != null) {
                out_stream.println(line);
            }
        } catch (Exception e) {throw new Error(e);}

        out_stream.flush();
    }
}
关于我的问题陈述:虽然脚本的执行大约需要17秒,“封装”的执行至少需要21秒。我在哪里损失这4秒或更长的时间

我已经尝试过使用
ProcessBuilder
将STDERR重定向到STDOUT,使用POSIX vWork和库,比如使用字节缓冲区而不是
BufferedReader
。。。一切都没有任何积极的结果

有什么建议吗?我知道会有一些性能损失,但4秒对我来说似乎有点太多了

感谢您的建议


提前向您致以最良好的问候和感谢

完成任务的最快方法是使用Java 7和

return new ProcessBuilder(cmdarray).inheritIO().start().waitFor();

如果这没有帮助,我想你也无能为力,因为其他任何方法都会向你的运行时环境中添加更多需要处理的代码。

不知道这是否会提高性能,但你可以试试这个库,它在提供非阻塞(异步)I/O的同时,也会在Linux上使用vWork,这确实大大减少了进程启动时间(和内存开销)。

我敢说4秒将是JVM预热时间:例如,将JVM可执行文件加载到内存中、加载标准库、加载类等。我猜是您使用线程引入的额外调度使您的速度变慢了。您是否尝试将脚本写入文件而不是
STDERR
STDOUT
?然后,您可以在不使用
ProcessInputStreamHandler
对象的情况下运行Java脚本包装器,以检查这是否还需要额外的4秒钟。如果是这种情况,非阻塞I/O(nio)可能会对您有所帮助。很好的一行代码,当然可以很好地清理代码。不幸的是,我的测试显示它没有提供任何性能优势…重要的一点是
inheritario()
,因为它不需要为输出重定向执行任何Java代码,而是让操作系统来处理。如果此功能不能提高性能,那么性能问题的原因根本不在于此代码。延迟可能源于将“外部”程序加载到JVM中。我做了进一步的测量来支持这一观点。感谢所有的建议和Java7提示,这对我来说是新的。