【问题标题】:Java ProcessBuilder.start() taking considerably longer than executing in a terminalJava ProcessBuilder.start() 比在终端中执行花费的时间要长得多
【发布时间】:2017-03-01 14:30:14
【问题描述】:

当用户单击按钮时,我有一个 GUI 会启动一个新线程 (getFilesThread)。该线程调用下面我的ClearCaseProcess 类实例的start() 方法(我的组织不允许我使用ClearCase Java API),当进程结束时,它会更新GUI。

private static class ClearCaseProcess {

private ArrayList<String> stdout = new ArrayList<>();
private ArrayList<String> stderr = new ArrayList<>();
private ProcessBuilder pb = null;

public ClearCaseProcess(ArrayList<String> commands, String dir) throws IOException {
    pb = new ProcessBuilder(commands);
    pb.directory(new File(dir));
}

public void start() throws IOException {
    long minStart = System.nanoTime();

    Process process = pb.start();

    Thread sout = new Thread() {
        @Override
        public void run() {
            BufferedReader out = new BufferedReader(
                new InputStreamReader(process.getInputStream()));

            String outLine = "";

            try {
                while ((outLine = out.readLine()) != null) {
                    stdout.add(outLine);
                    System.out.println(outLine);
                }
            } catch (IOException ex) {
                System.err.println(ex.getMessage());
            }
        }

    };
    sout.start();

    Thread serr = new Thread() {
        @Override
        public void run() {
            BufferedReader err = new BufferedReader(
                new InputStreamReader(process.getErrorStream()));

            String errLine = "";

            try {
                while ((errLine = err.readLine()) != null) {
                    stderr.add(errLine);
                    System.err.println(errLine);
                }
            } catch (IOException ex) {
                System.err.println(ex.getMessage());
            }
        }
    };
    serr.start();

    try {
        process.waitFor();
        long execTime = System.nanoTime() - minStart;
        System.out.println("Process '" + description + "' took " + execTime);
    } catch (InterruptedException ex) {
        System.err.println(ex.getMessage());
    }
}

}

getFiles() 需要从四个不同的ClearCaseProcesses 收集数据。我计划在四个线程中同时运行这些。这些线程中的每一个都有两个关联的辅助线程来消耗stdoutstderr,如上所示。我假设这将比连续运行四次 ClearCase 更快。不过,目前我只测试了一个 ClearCase 调用。

我的问题是调用Process.start() 和返回Process.waitFor() 之间经过的时间(大约5 分钟)比我在终端上运行相同的ClearCase 命令所经过的时间(大约1.5 分钟)要长得多。我怀疑我的读取 stdout 和 stderr 的循环是罪魁祸首,因为即使是我的打印语句在 NetBeans 控制台中产生输出的速度也很慢。如何加快速度?

【问题讨论】:

  • 您是否尝试过在 Netbeans 之外运行 Java 应用程序?
  • 嗯,奇怪。假设您首先关心的是运行时...您是否尝试过从这些流中读取任何内容?只需触发流程命令并测量执行时间?为了证明流会产生开销?
  • @GhostCat,如果进程实际上将任何内容发送到其输出和/或错误流中,那么 Java 程序必须必须使用它,否则外部进程可能永远不会终止。
  • 如果外部进程正在产生大量输出,那么问题可能与在两个列表中存储所有输出有关。您可以考虑将输出重定向到文件或空设备,或者将您阅读的所有内容都放在地板上。
  • 您是否在动态视图中使用它?你在用setview吗?您使用的是哪个版本的 ClearCase?在哪个操作系统上?

标签: java multithreading process clearcase


【解决方案1】:

对于我的具体情况,在 IDE 中运行(而不是调试)会导致开销。

从控制台 (java -jar myExecutable.jar) 运行时,时间非常接近。
愚蠢的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    • 2012-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多