使用 Java,ProcessBuilder
我正在创建一组子进程。我可以使用waitFor()
结果Process
对象中的方法来等待那个特定的孩子退出。
是否可以以 UNIX系统调用的方式阻塞直到任何子退出?wait()
使用 Java,ProcessBuilder
我正在创建一组子进程。我可以使用waitFor()
结果Process
对象中的方法来等待那个特定的孩子退出。
是否可以以 UNIX系统调用的方式阻塞直到任何子退出?wait()
第一步是将每个子流程完成的工作表示为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()
一次。
CountDownLatch 使用给定的计数进行初始化。由于调用了 countDown() 方法,等待方法一直阻塞,直到当前计数达到零,之后所有等待的线程都被释放,任何后续的 await 调用立即返回。这是一次性现象——计数无法重置。如果您需要重置计数的版本,请考虑使用 CyclicBarrier。
你必须使用某种形式的 IPC 来实现这一点。如果您被允许使用本机库并且您在 UNIX/Linux 平台上工作,请尝试通过编写一个简单的 JNI 包装器并从 java 代码调用本机方法来使用相同的 wait() 系统调用。
如果您不能使用本地 IPC 机制,请使用 TCP/IP 服务器/客户端机制,在该机制中,您可以在客户端连接/断开与服务器的连接时控制子进程从服务器退出。当没有子连接时,您可以退出服务器程序!