Могу ли я заставить приложение Java ожидать завершения фоновых процессов?

У меня есть скрипт bash на сервере и приложение Java, которое будет работать на указанном сервере. Моя цель — дважды вызвать этот сценарий из приложения Java, чтобы оба запускались одновременно.

У меня есть следующий код:

Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(new String[] { "/bin/bash", "-c", "script.sh & script.sh & " });

Это должно вызвать скрипт через bash, запустить его в фоновом режиме, а затем немедленно запустить еще один до завершения первого (скрипт выполняется около десяти секунд). Все это, кажется, работает отлично.

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

int exitValue = process.waitFor();
// "next line of code"

Однако кажется, что «следующая строка кода» выполняется до того, как оба процесса действительно завершились. Я подозреваю, что происходит то, что Java считает «процесс» завершенным, как только запускается второй процесс, поскольку они оба выполняются в фоновом режиме. Я предполагаю, что process.waitFor() действительно хорош только для отслеживания процессов переднего плана.

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


person user1015721    schedule 14.03.2015    source источник
comment
Для начала используйте не Runtime.exec(), а ProcessBuilder. Но да, это возможно.   -  person fge    schedule 14.03.2015
comment
Кроме того, что должно произойти, если один сценарий не будет выполнен правильно или оба?   -  person fge    schedule 14.03.2015


Ответы (2)


Вы можете запустить каждый из них в дочернем потоке, а затем «присоединиться» к этим потокам.

Runnable run1 = new Runnable()
{
    public void run()
    {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec(new String[] { "/bin/bash", "-c", "script.sh & script.sh & " });
    }
}

Runnable run2 = new Runnable()
{
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec(new String[] { "/bin/bash", "-c", "script2.sh & script2.sh & " });

}

Thread thread1 = new Thread(run1);
Thread thread2 = new Thread(run2);

thread1.start();
thread2.start();

thread1.join();
thread2.join();
person fdsa    schedule 14.03.2015

Я думаю, что вы не можете создать фоновую команду bash в вашем случае. & предназначен для команды, работающей в фоновом режиме, что позволяет выполнять реальную работу в фоновом режиме, но сообщает вам, что оболочка выполнена.

Runtime runtime =  Runtime.getRuntime(); 
Process process = runtime.exec(new String[] { "/bin/bash", "-c", "script.sh & script.sh " });
person ch271828n    schedule 14.03.2015