3

使用 Java,ProcessBuilder我正在创建一组子进程。我可以使用waitFor()结果Process对象中的方法来等待那个特定的孩子退出。

是否可以以 UNIX系统调用的方式阻塞直到任何子退出?wait()

4

3 回答 3

10

第一步是将每个子流程完成的工作表示为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()一次。

于 2011-01-07T07:08:13.857 回答
0

阅读有关CountDownLatch的信息

CountDownLatch 使用给定的计数进行初始化。由于调用了 countDown() 方法,等待方法一直阻塞,直到当前计数达到零,之后所有等待的线程都被释放,任何后续的 await 调用立即返回。这是一次性现象——计数无法重置。如果您需要重置计数的版本,请考虑使用 CyclicBarrier。

于 2011-01-07T05:14:49.093 回答
-2

你必须使用某种形式的 IPC 来实现这一点。如果您被允许使用本机库并且您在 UNIX/Linux 平台上工作,请尝试通过编写一个简单的 JNI 包装器并从 java 代码调用本机方法来使用相同的 wait() 系统调用。

如果您不能使用本地 IPC 机制,请使用 TCP/IP 服务器/客户端机制,在该机制中,您可以在客户端连接/断开与服务器的连接时控制子进程从服务器退出。当没有子连接时,您可以退出服务器程序!

于 2011-01-07T06:38:57.560 回答