2016-11-09 113 views
0

我有以下的集成測試代碼,我開始各種服務,然後測試才能運行:的Java:啓動過程中的一個線索,並得到一個參考所創建的進程

@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(); 
} 

過程開始OK,但我process.get()總是返回null。我究竟做錯了什麼?如何使用上述方法獲得對已啓動流程的引用?如果我在setup()函數本身設置了進程,即process = builder.start(),那麼它可以正常工作。但是,這也導致了很多重複,因爲我需要在單獨的JVM中啓動許多單獨的服務。

+0

移動'process.set(builder.start());'線程執行之前和之後'的AtomicReference 過程=新的AtomicReference <>();' – Stephan

+0

如果使用一個單獨的線程唯一原因是要使用進程的輸出,可以用'builder.inheritIO()。start();'替換整個launchProcess方法。 – VGR

回答

2

問題很可能是線程在launchProcess的末尾以process.get()返回時實際未啓動。

您需要等待線程在您的方法返回之前實際啓動並執行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(); 
} 
+0

謝謝,我已經給了這個和一個'Future'實現一個嘗試。雖然兩者都成功等待進程啓動,但在我開始啓動它們時,所有進程都具有'hasExited = true'。在這種情況下,我將如何防止線程退出?我只需要參考已啓動的流程。 – user991710

+0

是否有任何理由需要在單獨的線程中啓動它?如果你需要這個線程,那麼你需要通過在進程對象上調用'waitFor'來讓線程等待,直到進程完成。 –

+0

在獨立線程中啓動它們的主要原因是爲了能夠啓動和運行服務並行地,即不必等待它們中的每一個單獨啓動。我會試一試'waitFor'方法。 – user991710

相關問題