Java:在线程中启动进程并获取对已创建进程的引用
我有以下集成测试代码,在测试运行之前启动各种服务:Java:在线程中启动进程并获取对已创建进程的引用,java,process,Java,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); }
@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();
}
@BeforeClass
public static void setup()引发异常{
//设置一些变量,比如javaBin location
ProcessBuilder=newProcessBuilder(javaBin,“-jar”,“app.jar”);
过程=启动过程(生成器);
}
私有静态进程启动进程(ProcessBuilder生成器)引发IOException{
AtomicReference进程=新的AtomicReference();
新线程(()->{
试一试{
process.set(builder.start());
BufferedReader processStd=新的BufferedReader(新的InputStreamReader(process.get().getInputStream());
BufferedReader ProcessError=新的BufferedReader(新的InputStreamReader(process.get().getErrorStream());
//防止由于缓冲区大小有限而导致死锁
字符串s=“”;
而(processStd.readLine()!=null){}
而((s=processErr.readLine())!=null){
系统错误打印项次;
}
}
捕获(IOE异常){
e、 printStackTrace();
}
}).start();
返回进程get();
}
进程启动正常,但我
process.get()
始终返回null
。我做错了什么?如何使用上述方法获取对已启动进程的引用?如果我在setup()
函数本身中设置进程,即process=builder.start()
,那么它就可以正常工作。但是,这也会导致大量重复,因为我需要在不同的JVM中启动许多不同的服务。问题很可能是,当您在启动过程
结束时返回process.get()
时,线程还没有真正启动
在从方法返回之前,您需要等待线程实际启动并执行对process.set(builder.start())
的调用
这可以通过像倒计时闩锁这样简单的方法来实现
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();
}
问题很可能是,当您在launchProcess
结束时使用process.get()
返回时,线程尚未实际启动
在从方法返回之前,您需要等待线程实际启动并执行对process.set(builder.start())
的调用
这可以通过像倒计时闩锁这样简单的方法来实现
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();
}
在线程实现之前和之后移动process.set(builder.start());
如果使用单独线程的唯一原因是使用进程的输出,则可以使用builder.inheritIO().start()替换整个launchProcess方法
.moveprocess.set(builder.start());
在线程实现之前和之后AtomicReference process=new AtomicReference();
如果使用单独线程的唯一原因是使用进程的输出,则可以使用builder.inheritIO().start()替换整个launchProcess方法
。谢谢,我已经尝试了这两种方法和未来的实现。虽然这两种方法都成功地等待进程启动,但在我启动它们时,所有进程都已hasExited=true
。在这种情况下,如何防止线程退出?我只需要一个对正在启动的进程的引用已启动。是否有任何原因需要在单独的线程中启动此程序?如果需要该线程,则需要通过在process Object上调用waitFor
使线程等待进程完成。在单独的线程中启动这些程序的主要原因是能够使服务并行启动和运行,即不需要必须等待它们各自单独启动。我将尝试一下waitFor
方法。我们最终只编写了一个shell脚本来执行各自项目中的jar
文件。它比提供的用例简单得多,但满足了我们的需要。我仍然会将此标记为一个答案,因为它确实是这样做的回答这个问题。谢谢,我已经尝试了这两种方法和未来
实现。虽然这两种方法都成功地等待进程启动,但在我启动它们时,所有进程都已hasExited=true
。在这种情况下,我如何防止线程退出?我只需要对进程的引用已启动。是否有任何原因需要在单独的线程中启动此操作?如果需要该线程,则需要通过调用process Object上的waitFor
,让该线程等待进程完成。在单独的线程中启动它们的主要原因是能够启动服务并并行运行,即.e.不必等待它们各自独立启动。我将尝试一下waitFor
方法。我们最终只编写了一个shell脚本来执行各自项目中的jar
文件。它比提供的用例简单得多,但满足了我们的需要。我仍然会像在中一样将此标记为一个答案请回答这个问题。