在Java中,使用Runtime.getRuntime()。exec和p.waiFor()确实会为短期任务带来大量开销

时间:2018-07-20 21:46:48

标签: java runtime.exec

在我的Java应用程序中,有时我必须调用非Java命令行应用程序来处理文件。我经常处理20个文件,对于每个文件,我使用 Runtime.getRuntime()。exec 来运行命令,附加一个进程以侦听输出和错误输出,并等待任务完成。 / p>

在我的PC上,它可以正常工作,但是在相当慢的NAS设备上,通过Java运行任务的速度似乎要慢一些,如果直接从命令行运行它们,则每个任务持续几秒钟,可能还要再花几秒钟比从命令行。随着时间的流逝,这种明显的差异是相当大的(在PC上注意,每个任务仅花费大约200毫秒)。

从Java调用,创建线程以侦听输出并等待完成会产生大量开销。我是否应该重写代码以创建一个可以处理所有文件的脚本,所以我只需要一个 Runtime.getRuntime()。exec 和两个Strokem Gobbler。

因为我需要考虑有时会失败的任务,所以困难在于可靠地解析输出,所以我的问题是,是否有任何意义,会有所作为

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamGobbler implements Runnable {
    private InputStream     inputStream;
    private StringBuilder   output;

    public StreamGobbler(InputStream inputStream, StringBuilder output) {
        this.inputStream = inputStream;
        this.output = output;
    }

    @Override
    public void run()
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        try
        {
            String s = br.readLine();
            if (s != null)
            {
                output.append(s);
            }
            br.close();
        }
        catch(IOException ioe)
        {

        }
    }
}

List<String> params = new ArrayList();
params.add(new File(SongKong.exeFolder, "fpcalc").getAbsolutePath());
params.add(file.getPath());
p = Runtime.getRuntime().exec(params.toArray(new String[1]));

    StringBuilder output        = new StringBuilder();
    StringBuilder errorOutput   = new StringBuilder();
    StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(), output);
    StreamGobbler errorGobbler  = new StreamGobbler(p.getErrorStream(), errorOutput);
    Executors.newSingleThreadExecutor().execute(outputGobbler);
    Executors.newSingleThreadExecutor().execute(errorGobbler);
    p.waitFor();
    fingerprint = output.toString();

1 个答案:

答案 0 :(得分:0)

您想知道是否重写应用程序以执行脚本而不是多个exec会影响执行时间。

可能会。但是,如果不了解exec命令执行速度为何缓慢,我们就无法告诉您它会产生多大的变化……以及是否值得付出努力。

我建议您使用Java做一些简单的实验:

  • 比较运行某些简单命令(例如exec("echo hello"))20次,而不是执行执行相同操作的脚本:

  • 做同样的事情,涉及存储在NAS上的输入文件

  • 执行涉及存储在NAS上的可执行文件的操作(如果相关)

这些实验应该可以帮助您确定建议的加速应用程序的方法是否可行。

如果您的外部命令是在类路径上具有许多JAR且这些JAR位于NAS上的Java命令,那么可能会严重影响启动时间。 / p>