2009-08-05 15 views
2

スレッドの経験がかなり少ないことをまず教えてください。Javaスレッドの質問 - n個のエラーストリームをリッスンする

Runtime.execメソッドを使用して、他のいくつかのJava jarを起動するアプリがあります。問題は、開始されたjarファイルは同時に実行する必要がありますが、開始されたjarのエラーストリームを取得するには、プロセスが完了するまで基本的にループを「座って聴く」必要があります。

これは私が今持っているものです。

_processes.add(Runtime.getRuntime().exec(commandList.toArray(new String[ commandList.size() ]))); 
Thread thread = new Thread(new Runnable() { 
    private final int _processNumber = _processes.size() - 1; 
    public void run() { 
     String streamData = _processNumber + " : "; 
     streamData += "StdError [\r"; 
     BufferedReader bufferedReader = 
       new BufferedReader(new InputStreamReader(_processes.get(_processNumber).getErrorStream())); 
     String line = null; 
     try { 
      while ((line = bufferedReader.readLine()) != null) { 
       streamData += line + "\r"; 
      } 
      bufferedReader.close(); 
      streamData += "]\r"; 
      LOG.error(streamData); 
     } 
     catch (Exception exception) { 
      LOG.fatal(exception.getMessage()); 
      exception.printStackTrace(); 
     } 
    } 
}); 
thread.start(); 

、誰もが「エラーストリームリスナー・スレッドは、」正常に動作させるためにどのように説明できますか?

TIA

答えて

0

のRuntime.exec()を使用する方法についての非常に良いチュートリアルhereがあります。特に、4ページを参照してください。ここでは、別のスレッドで実行されている 'StreamGobbler'を使用して、実行中のプロセスからstd outストリームとstd errストリームの両方を消費する方法について説明します。

基本的に、何をpseduoコードで実装するために探してすべきことである。

Runtime rt1 = Runtime.getRuntime().exec("my command") 
new StreamGobbler(rt1.getOutputStream()).start() 
new StreamGobbler(rt1.getErrorStream()).start() 
//repeat for each external process (rt2, rt3 etc) 
... 
rt1.waitFor() 
rt2.waitFor() 
rt3.waitFor() 

すなわち、各プロセスを開始し、すぐに別のスレッドで各プロセスの出力を消費し始めます。消費スレッドを開始したら、各プロセスが終了して戻るのを待ってください。

+0

ええ、これまでに読んだことがあります。問題は、rt1がリスニングソケットを開き、rt2がソケットの書き込み側をオープンしていることです。 rt1のストリームから2つのスレッドを開始すると、親スレッドがブロックされてrt2が起動しないように見えます。私はすべてのexecコマンドを実行してからすべてのリスナーを起動しようとしました。これを実行するとexec'edコマンドが強制的にブロックされます。 – javamonkey79

1

代わりRuntime.getRuntimeを(使用)のexec()、外部プロセスを起動するためにProcessを使用...それはあなたの人生がずっと簡単に作ってあげる私のプロジェクトから..

例コード:

//Build command 
    List<String> commands = new ArrayList<String>(); 
    commands.add("my_application"); 
    commands.add("arg1"); 
    commands.add("arg2"); 
    log.debug("{}", commands); 

    //Run command with arguments 
    ProcessBuilder pb = new ProcessBuilder(commands); 
    pb.directory(directory); 
    pb.redirectErrorStream(true); 
    Process process = pb.start(); 

    //Read output 
    StringBuilder out = new StringBuilder(); 
    BufferedReader br = new BufferedReader(new InputStreamReader 
     (process.getInputStream())); 

    //Only log unique lines (you might not need this) 
    String line = null, previous = null; 
    while ((line = br.readLine()) != null) 
     if (!line.equals(previous)) { 
      previous = line; 
      out.append(line).append('\n'); 
      log.debug(line); 
     } 

    //Check result 
    if (process.waitFor() == 0) 
     return 0; 

    //Abnormal termination: Log command parameters and output and throw ExecutionException 
    log.error("{}", commands); 
    log.error("\n{}", out.toString()); 
    throw new ExecutionException(new IllegalStateException("MyApplication exit code 1")); 
+0

私は、スポーンされたスレッドとそれに対応するストリームの並行性が問題だと思います。私はProcessBuilder(あるいはJavaのすべてで重要なこと)がプロセスをはるかに上手く処理することはあまり見られません。 jconfigは上記の記事で言及されていますが、明らかにプロジェクトはかなり死んでいます(少なくとも現在は)。 – javamonkey79

+0

PipedOut/InputStreamはここより助けになるでしょうか? – Tim