2016-11-09 8 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開始しますが、 I process.get()は常にnullを返します。私は間違って何をしていますか?上記の方法を使用して、開始したプロセスへの参照を取得するにはどうすればよいですか? setup()関数内にプロセスを設定した場合、すなわちprocess = builder.start()の場合、正しく動作します。しかし、それは別のJVMで数多くの別々のサービスを開始する必要があるので、多くの繰り返しにつながります。

+0

動き 'process.set(builder.start());'スレッド実装前後のAtomicReference 'プロセス=新しいAtomicReference <>();' – Stephan

+0

別のスレッドを使用するための唯一の理由がある場合プロセスの出力を消費するには、launchProcessメソッド全体を 'builder.inheritIO()。start();'に置き換えることができます。 – 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

関連する問題