Первый шаг - представить работу, выполненную каждым подпроцессом, как 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()
один раз.