2017-06-20 15 views
-1

我有一個多線程程序,它在一定條件下顯示奇怪的行爲。由於專有的問題,我不能在這裏發佈完整的代碼,但我在這裏提供了示例bug。即使在mutithreaded popgram條件滿足的情況下while循環不會以java結尾

我已經具有一個布爾變量,並延伸Java線程類中的一個類

公共類SystemStreamCapture擴展Thread {

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; 
} 

}

此線程其它類內使用如下:

公共級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循環。即使「完成」變量變爲「真」,循環也不會結束。我也試過語法'(outStream.isDone() == false)',只是爲了看看它是否有所作爲(我知道不會)。 但是,只要我在內部轉入'Log.debug("reading...")',它就會按預期工作。

我不知道發生了什麼,也許outStream.isDone()調用嘗試將布爾值複製到新的內存地址,無情的輪詢不允許它。

請分享你在這個問題上的經驗和知識。

+0

不看那堆代碼,一條規則:在'finally'語句中關閉流,或者使用try-with-resources。 – Mena

+0

您是否檢查過文檔以查看您應該如何閱讀'getErrorStream'?有一個檢查,如果它仍然是'可用'()'你沒有使用。欲瞭解更多信息:https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html – alfasin

+0

使'完成''易揮發'。 –

回答

2

在多線程環境中,你需要可視性當一個線程改變一個值應該看到其他thread.For你的情況下,你可以使用volatile boolean flag或使用AtomicBoolean變量類型,因此它會向其他線程可見,當一個線程改變的價值。

volatile boolean done = false; 
+0

請編輯您的答案以顯示_which_變量應該是'volatile'。 – Gray

+0

謝謝,它有幫助。 –

+0

@vaibhav singh如果你認爲它適合你投票,所以它會對其他人有幫助。 –

相關問題