2011-01-07 4 views
3

Использование Java ProcessBuilder Я создаю группу дочерних процессов. Я могу использовать метод waitFor() из результирующего объекта Process, чтобы дождаться выхода этого конкретного ребенка.Java, подождите, пока дочерний процесс завершится

Можно ли заблокировать до какой-либо ребенок выходит в порядке системного вызова UNIX wait()?

ответ

0

пользователя о CountDownLatch

A CountDownLatch инициализируется с данного графа. Методы Await блокировать , пока текущее значение счетчика не достигнет нулевого из-за вызовами CountDown() метод, после чего все ожидающие потоки будут освобождены и любые последующие вызовы ждут возвращения немедленно. Это одноразовый феномен - количество не может быть сброс. Если вам нужна версия, которую сбрасывает счет, подумайте об использовании CyclicBarrier.

-2

Для достижения этой цели вам необходимо использовать некоторую форму IPC. Если вам разрешено использовать собственные библиотеки, и если вы работаете на платформе UNIX/Linux, попробуйте использовать тот же системный вызов wait(), написав простую обертку JNI &, вызывающую собственный метод из java-кода.

Если вы не можете использовать собственные механизмы IPC, используйте механизм TCP/IP server/client, в котором вы контролируете выход дочернего процесса с сервера, когда клиент подключается/отключается от сервера. Когда нет дочерних подключений, вы можете выйти из программы сервера!

+0

Нет такой вещи, как простая обертка JNI. :) – sjr

+0

Понятие о том, что использование JNI должно быть вызвано здесь, кажется явно странным, также простите мое невежество, но я не знал, что такое «какая-то форма IPC», ваш ответ ничего не сделал, чтобы сообщить мне, и даже быстрый google didn ' t помочь. Извините, я не очень часто спускаюсь вниз, но это действительно не кажется мне полезным. – PeterT

9

Первый шаг, чтобы представить работу каждого подпроцесса как Future, например, так:

final ProcessBuilder builder = ...; 

// for each process you're going to launch 
FutureTask task = new FutureTask(new Callable<Integer>() { 
    @Override public Integer call() { 
    return builder.start().waitFor(); 
    } 
}; 

Теперь представить все задачи исполнителя:

ExecutorService executor = Executors.newCachedThreadPool(); 
for (FutureTask task : tasks) { 
    executor.submit(task); 
} 

// no more tasks are going to be submitted, this will let the executor clean up its threads 
executor.shutdown(); 

Теперь использовать отличную ExecutorCompletionService класс:

ExecutorCompletionService service = new ExecutorCompletionService(executor); 
while (!executor.isTerminated()) { 
    Future<Integer> finishedFuture = service.take(); 
    System.out.println("Finishing process returned " + finishedFuture.get()); 
} 

Этот цикл будет повторяться один раз накануне когда он заканчивается. returnValue будет кодом выхода дочернего процесса.

Теперь вы точно не знаете, какой процесс завершился. Вы можете изменить Callable вместо того, чтобы возвращать Integer, чтобы просто вернуть Process или даже лучше ваш собственный класс, представляющий результат процесса.

О, и, конечно, если вы не заботитесь о ожидании всех задач, вы можете просто позвонить take() один раз.

+0

Есть ли книга, в которой говорится об этом как о шаблоне дизайна. Он, похоже, очень похож на образец потребительского дизайна производителя. Однако Исполнители и Будущее для меня что-то новое.У вас есть дополнительный источник для чтения. Заранее спасибо. – JourneyMan

+0

Я хочу, чтобы 'waitFor()' выходил слишком рано, когда я запускал 'cmd.exe/C start BAT', я добавил команду'/wait' в команду cmd и работал как ожидалось. ;-) – Kalaschni

Смежные вопросы