我有以下集成测试代码,我可以在测试运行之前启动各种服务:
@BeforeClass
public static void setup() throws Exception {
// Set some vars like javaBin location
ProcessBuilder builder = new ProcessBuilder(javaBin, "-jar", "app.jar");
Process process = launchProcess(builder);
}
private static Process launchProcess(ProcessBuilder builder) throws IOException {
AtomicReference<Process> process = new AtomicReference<>();
new Thread(() -> {
try {
process.set(builder.start());
BufferedReader processStd = new BufferedReader(new InputStreamReader(process.get().getInputStream());
BufferedReader processErr = new BufferedReader(new InputStreamReader(process.get().getErrorStream()));
// To prevent deadlocks due to limited buffer size
String s = "";
while(processStd .readLine() != null) {}
while((s = processErr .readLine()) != null) {
System.err.println(s);
}
}
catch (IOException e) {
e.printStackTrace();
}
}).start();
return process.get();
}
该过程开始正常,但我process.get()
始终返回null
。我究竟做错了什么?如何使用上述方法获得对已启动流程的引用?如果我在setup()
函数本身设置过程,即process = builder.start()
,那么它可以正常工作。但是,它还会导致大量重复,因为我需要在单独的JVM中启动大量单独的服务。
答案 0 :(得分:2)
问题很可能是在process.get()
结尾处launchProcess
返回时,线程实际上尚未启动。
在从方法返回之前,您需要等待线程实际启动并执行对process.set(builder.start())
的调用。
这可以通过像CountDownLatch
这样简单的事情来完成。
private static Process launchProcess(ProcessBuilder builder) throws IOException {
final CountDownLatch latch = new CountDownLatch(1);
// ...
new Thread(() -> {
try {
process.set(builder.start());
latch.countDown();
//...
} catch (IOException e) {
//...
}
}).start();
latch.await();
return process.get();
}