帮助在多个线程上运行Java runtime.exec()

帮助在多个线程上运行Java runtime.exec(),java,process,Java,Process,在我的程序中,我需要使用java在Ubuntu环境(ntpdate)中运行一个外部命令。当前我的代码如下所示: Runtime rt = Runtime.getRuntime(); byte[] readBuffer = new byte[131072]; // Exec a process to do the query Process p = null; try { p = rt.exec("ntpdate -q " + ip);

在我的程序中,我需要使用java在Ubuntu环境(ntpdate)中运行一个外部命令。当前我的代码如下所示:

    Runtime rt = Runtime.getRuntime();

    byte[] readBuffer = new byte[131072];
    // Exec a process to do the query
    Process p = null;
    try {
        p = rt.exec("ntpdate -q " + ip);
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    if(p!= null){
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
        }

        // Read the input stream, copy it to the file
        InputStream in = p.getInputStream();


        try {
            int count = 0, rc;
            while ((rc = in.read(readBuffer, count, readBuffer.length - count)) != -1) {
                count += rc;
                if (count >= readBuffer.length) {
                    p.destroy();
                    break;
                }
            }
            p.destroy();
            result = processOutput(readBuffer, count);

        } catch (IOException ex) {
            ex.printStackTrace();
        }
        p.destroy();
这段代码需要在多个线程上同时运行,以最大限度地提高性能(我需要使用ntpdate测试1.000.000个地址的列表)。然而,它运行非常缓慢,几乎不消耗机器处理。我做错了什么?我怎样才能提高效率


尝试使用.exec()执行“dig”时也会出现同样的问题,因此我怀疑这是因为调用了特定的程序。在多线程环境中使用Runtime.exec()是否有一些限制?

Java是最合适的方法吗?也许这在shell脚本中会更好,它在后台多次调用
ntpdate
?我不确定在Java中这样做会给您带来什么好处

您如何处理流程中的
InputStream


bash脚本可以执行以下操作:

for ip in #...IP list
do
  ntpdate -q $ip > $ip.txt &
done

为什么每次都要等一秒钟

try {
    Thread.sleep(1000);
} catch (Exception e) {
}

这只会减慢应用程序的执行速度。

不确定为什么会变慢,但您需要做更多的工作来关闭资源。Runtime.exec()需要非常小心,以避免挂起和泄漏文件描述符


您确定问题不是最新的吗?如果ntpdate只是坐在那里等待服务器响应,并且有一个很大的超时值,那么您的应用程序也将坐在那里

尝试在超时为0.2的情况下调用ntpdate,看看这是否会产生影响


此外,当您在代码中打开流时,您肯定希望在完成后显式地.close()关闭它们。否则,它可能在GC之前不会发生,而GC可能需要很长时间。

我注意到您尝试的两个命令都涉及网络往返。如果改为调用
echo
cat
之类的函数,速度如何?

我想我找到了解决方案,那就是没有使用java的Runtime.exec()的解决方案。问题似乎是启动进程的所有调用都是同步的。事实上,如果您单独启动每个进程(通过同步),您将得到完全相同的结果,即同时启动所有进程


exec还有其他选择吗?否则,我将需要在没有linux的NTUpdate的情况下获得一些解决方案…

以及“几乎不使用机器处理”我正在尝试修复其他人的代码。我不记得为什么会这样,但是删除它并不能解决问题。我使用的是一个通用的线程初始化类,它适用于其他情况。当我试图调用Runtime.exec()时,这些线程似乎相互锁定,它们应该相互独立。我需要解析输出数据并将其插入数据库。此外,数据来自数据库。我之所以使用Java,是因为我已经构建了一个框架来进行类似的测试,但没有使用外部调用。它可以在shell脚本上实现,但我希望为Java找到一个解决方案,因为同样的问题也发生在另一个我不能使用shell脚本的情况下。也许最好的方法是使用Java ntp库,而完全放弃使用shell命令。因为ntp似乎是一个合理的方法。无论如何,不依赖OS外壳命令更便于移植。由于超时,我在多个线程中调用它。然而,我甚至不能启动我设置的所有线程,好像有什么东西阻塞了其他线程。但是谢谢你记得我关于关闭溪流的事。你说的是多少条线。也许它应该是一个可调整的值。如果你有100万个线程,你可能需要同时产生500个线程才能在一天内完成列表。考虑使用线程池样式架构来控制它可能是一个好主意。对于Java5并发,您可以使用阻塞队列和执行器服务来生成可调数量的工作线程。每次一个任务完成后,你可以为下一个线程排队一个新地址,这是免费的。是的,这就是我正在使用的。然而,在处理列表的一半之前,线程甚至还没有完成启动。在100到2000个线程中,我得到了大致相同的结果(时间方面)。刚刚测试过。如果我在多线程中启动大量echo,那么完成它们的总时间会随着它们的并行性增加而增加。一个有趣的实验:在尝试在每个线程中进行回显之前等待1秒钟。所花的时间是它们按顺序执行所需时间的6倍。我试图与exec一起运行的所有其他事情都是如此,远远超出了我的解释范围。我似乎对java exec实现存在一些问题。还有其他选择吗?