Помогите запустить Java runtime.exec () в нескольких потоках - PullRequest
2 голосов
/ 25 августа 2010

В моей программе мне нужно запустить внешнюю команду в среде Ubuntu (ntpdate), используя java. В настоящее время мой код выглядит так:

    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();

Этот код должен выполняться одновременно в нескольких потоках, чтобы максимизировать производительность (мне нужно протестировать список из 1.000.000 адресов с помощью ntpdate). Тем не менее, он работает очень медленно, почти не требует машинной обработки. Что я делаю неправильно? Как я могу сделать это более эффективным?

Та же проблема возникает при попытке выполнить «копание» с помощью .exec (), поэтому я сомневаюсь, что это из-за конкретной вызываемой программы. Существуют ли ограничения в использовании Runtime.exec () в многопоточной среде?

Ответы [ 6 ]

2 голосов
/ 25 августа 2010

Является ли Java наиболее подходящим подходом здесь? Возможно, это было бы лучше в сценарии оболочки, который вызывает ntpdate в фоновом режиме несколько раз? Я не уверен, какую выгоду вы получите от этого фрагмента кода, делая это на Java.

Что вы делаете с InputStream из процесса?


Сценарий bash может сделать это следующим образом:

for ip in #...IP list
do
  ntpdate -q $ip > $ip.txt &
done
1 голос
/ 27 августа 2010

Я думаю, что нашел решение, и это то, что нет решения, использующего java Runtime.exec ().Кажется, проблема в том, что все вызовы для запуска процесса синхронизированы.В самом деле, если вы запускаете каждый процесс отдельно (через синхронизацию), вы получаете точно такой же результат запуска всех процессов вместе.

Есть ли альтернативы exec?В противном случае мне нужно будет найти какое-то решение без ntpdate в linux ...

1 голос
/ 25 августа 2010

Вы уверены, что проблема не в ntpdate?Если ntpdate просто сидит в ожидании ответа сервера и имеет большое значение тайм-аута, то ваше приложение тоже будет сидеть там.

Попробуйте вызвать ntpdate с тайм-аутом 0.2 и посмотрите, имеет ли это значение.

Кроме того, когда вы открываете потоки в своем коде, вы определенно хотите явно .close () их, когда закончите.В противном случае это может не произойти, пока GC не будет очень долго.

1 голос
/ 25 августа 2010

Не знаю, почему это медленно, но вам нужно сделать гораздо больше, чтобы закрыть свои ресурсы.Runtime.exec () требует некоторой осторожности и внимания, чтобы избежать зависаний и утечки файловых дескрипторов.

http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

1 голос
/ 25 августа 2010

Почему вы ждете по 1 секунде каждый раз?

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

Это ничего не даст, кроме замедления выполнения вашего приложения.

0 голосов
/ 25 августа 2010

Я замечаю, что обе команды, которые вы пробовали, включают обходы по сети.Какова скорость, если вы называете что-то вроде echo или cat вместо?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...