Java: 在线程中启动一个进程并获取对已创建进程的引用
Java: Starting a process in a thread and getting a reference to the created process
我有以下集成测试代码,我在测试之前启动各种服务 运行:
@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()
总是returnsnull
。我究竟做错了什么?如何使用上述方法获取对已启动流程的引用?如果我在 setup()
函数本身中设置进程,即 process = builder.start()
,那么它可以正常工作。但是,这也导致了很多重复,因为我需要在单独的 JVM 中启动许多单独的服务。
问题很可能是线程在您 return 和 process.get()
在 launchProcess
结束时实际上尚未启动。
您需要等待线程实际启动并执行对 process.set(builder.start())
的调用,然后才能从您的方法中 returning。
这可以用像 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();
}
我有以下集成测试代码,我在测试之前启动各种服务 运行:
@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()
总是returnsnull
。我究竟做错了什么?如何使用上述方法获取对已启动流程的引用?如果我在 setup()
函数本身中设置进程,即 process = builder.start()
,那么它可以正常工作。但是,这也导致了很多重复,因为我需要在单独的 JVM 中启动许多单独的服务。
问题很可能是线程在您 return 和 process.get()
在 launchProcess
结束时实际上尚未启动。
您需要等待线程实际启动并执行对 process.set(builder.start())
的调用,然后才能从您的方法中 returning。
这可以用像 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();
}