Java,等待子进程退出

3
使用Java的ProcessBuilder,我正在创建一组子进程。我可以使用生成的Process对象的waitFor()方法等待特定的子进程退出。
是否可能以类似UNIX wait()系统调用的方式阻塞,直到任何子进程退出?
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 更改为返回一个 Process 或者更好地,返回一个表示进程输出的自定义类,而不是返回一个整数。

当然,如果您不关心等待所有任务,则只需调用一次take()


有没有一本书讲述这个作为设计模式。它似乎非常类似于生产者消费者设计模式。然而,Executors和Future对我来说是新的东西。你有任何额外的资源可以阅读吗?提前谢谢。 - Dhawan Gayash
我遇到了一个问题,当我运行 cmd.exe /C start BAT 时,waitFor() 提前退出了。我在 cmd 命令中添加了 /wait,它按预期工作了。;-) - Kalaschni

0

阅读关于CountDownLatch的内容

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


-2

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

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


没有所谓的简单JNI包装器。 :) - sjr
使用JNI似乎在这里被称为是非常奇怪的想法,同时请原谅我的无知,我不知道“某种形式的IPC”是什么,你的回答并没有让我了解更多,即使是快速搜索也没有帮助。很抱歉,我很少会点踩,但这真的让我感觉没有用。 - PeterT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接