使用Java的
是否可能以类似UNIX
ProcessBuilder
,我正在创建一组子进程。我可以使用生成的Process
对象的waitFor()
方法等待特定的子进程退出。是否可能以类似UNIX
wait()
系统调用的方式阻塞,直到任何子进程退出?ProcessBuilder
,我正在创建一组子进程。我可以使用生成的Process
对象的waitFor()
方法等待特定的子进程退出。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 更改为返回一个 Process 或者更好地,返回一个表示进程输出的自定义类,而不是返回一个整数。
当然,如果您不关心等待所有任务,则只需调用一次take()
。
阅读关于CountDownLatch的内容
CountDownLatch是使用给定的计数初始化的。await方法会阻塞,直到由于countDown()方法的调用而使当前计数达到零,此后所有等待的线程都将被释放,并且任何随后的await调用都将立即返回。这是一个一次性现象--计数无法重置。如果您需要一个可以重置计数的版本,请考虑使用CyclicBarrier。
你必须使用某种形式的IPC来实现这一点。如果允许使用本地库并且在UNIX/Linux平台上工作,请尝试编写一个简单的JNI包装器并从Java代码调用相同的wait()系统调用。
如果无法使用本地IPC机制,请使用TCP/IP服务器/客户端机制,在其中通过控制子进程从服务器退出,而客户端连接/断开与服务器连接。当没有子连接时,您可以退出服务器程序!
cmd.exe /C start BAT
时,waitFor()
提前退出了。我在 cmd 命令中添加了/wait
,它按预期工作了。;-) - Kalaschni