2017-06-20 3 views
-1

私はある特定の条件で奇妙な動作を示しているマルチスレッドプログラムを持っています。独自の問題のため、ここに完全なコードを投稿することはできませんが、私はここにバグの例を載せています。whileループはmutithreaded popgramで条件が満たされても終了しません

Iはブール変数を有する1つのクラスを持っているとJavaスレッドクラス

パブリッククラスSystemStreamCaptureは、以下のように、このスレッドは、他のクラス内で使用されるスレッド{

InputStream is; 
boolean done = false; 
List<String> buffer; 

private final static Logger Log = Logger.getLogger(SystemStreamCapture.class); 

public SystemStreamCapture(InputStream is) { 
    this.is = is; 
} 


public void run() { 
    try { 
     InputStreamReader isr = new InputStreamReader(is); 
     BufferedReader br = new BufferedReader(isr); 
     String line = null; 
     while ((line = br.readLine()) != null) { 
      this.buffer.add(line); 
     } 
     br.close(); 
     isr.close() 
    } catch (IOException ioe) { 
     Log.error(ioe); 
    } finally { 
     this.done = true; 
    } 
} 

public List<String> getData() { 
    return this.buffer; 
} 

public boolean isDone() { 
    return this.done; 
} 

}

を拡張延びています:

public class FileReader {

private final static Logger Log = Logger.getLogger(FileReader.class); 

public List<String> readLines(FileLineRequestModel request) throws IOException { 
    String[] script = { "/bin/sh", "-c", request.getCommand() }; 
    Log.debug("executing line fetch command : " + request.getCommand()); 

    Process p = Runtime.getRuntime().exec(script); 

    SystemStreamCapture errStream = new SystemStreamCapture(p.getErrorStream()); 
    SystemStreamCapture outStream = new SystemStreamCapture(p.getInputStream()); 

    errStream.start(); 
    outStream.start(); 

    while (!outStream.isDone()) { 
     // keep looping 
//Log.debug("reading..."); 
    } 
    return outStream.getData(); 

} 

奇妙な部分は、後のクラスのwhileループです。 "done"変数が "true"になってもループは終了しません。私は文法 '(outStream.isDone() == false)'も試してみました。違いがあるかどうかは分かりません。 しかし、私が 'Log.debug("reading...")'を中に入れたら、期待どおりに動作します。

私はいただきました!起こっ見当がつかない、多分outStream.isDone()の呼び出しは、新しいメモリアドレスにブールコピーしようと執拗なポーリングはそれを許可していません。

この問題に関するご経験と知識をお寄せください。

+0

コードの山を見ることなく、1つのルール:ストリームを「finally」ステートメントで閉じたり、try-with-resourcesを使用したりしてください。 – Mena

+0

'getErrorStream'をどのように読むべきかを調べるためにドキュメントをチェックしましたか?あなたがまだ使用していない 'available()'かどうかのチェックがあります。詳細はhttps://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html – alfasin

+0

「実行済み」を「揮発性」にしてください。 –

答えて

2

マルチスレッド環境では、1つのスレッドが1つの値を他のスレッドに見えるように変更する必要があります。volatile boolean flagを使用するか、AtomicBoolean変数タイプを使用すると、1つのスレッドが値を変更すると、

volatile boolean done = false; 
+0

答えを編集して_which_変数を 'volatile'にする必要があります。 – Gray

+0

ありがとうございます。 –

+0

@vaibhav singhそれがあなたの投票のためにうまくいくと思うなら、それは他人のために役立つでしょう。 –

関連する問題