Java, wait for child process to exit
Using Java's ProcessBuilder
I am creating a group of child processe开发者_如何学编程s. I can use the waitFor()
method from the resulting Process
object to wait for that particular child to exit.
Is it possible to block until any child exits, in the manner of the UNIX wait()
system call?
First step is to represent the work done by each subprocess as a Future, like so:
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();
}
};
Now submit all the tasks to an executor:
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();
Now use the excellent ExecutorCompletionService class:
ExecutorCompletionService service = new ExecutorCompletionService(executor);
while (!executor.isTerminated()) {
Future<Integer> finishedFuture = service.take();
System.out.println("Finishing process returned " + finishedFuture.get());
}
This loop will iterate once for every completing task as it finishes. The returnValue
will be the exit code of the child process.
Now, you don't know exactly which process has finished. You could change the Callable to instead of returning an Integer to just return the Process or even better a class of your own representing the output of the process.
Oh and of course if you don't care about waiting for all the tasks, you can just call take()
once.
Read about the CountDownLatch
A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.
you have to use some form of IPC to achieve this. If you are allowed to use native libraries and if you work on UNIX/Linux platform try using the same wait() system call by writing a simple JNI wrapper & calling the native method from java code.
If you cannot use native IPC mechanisms use TCP/IP server/client mechanism in which you control the child process exit from the server while the client connects/disconnects to/from the server. When there are no child connections you can exit the server program!
精彩评论