我有一个多线程程序,它在某种特定条件下显示出奇怪的行为。由于专有问题,我不能在这里发布完整的代码,但我在这里提出示例错误。
我有一个类,它有一个布尔变量,并且正在扩展Java Thread类
public class 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;
}
}
此Thread在其他类中使用如下:
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循环。尽管“完成”变量变为“真”,但循环永远不会结束。我还尝试了语法'(outStream.isDone() == false)
',只是为了看它是否有所不同(我知道不会)。
但是,当我在内部转换“Log.debug("reading...")
”时,它会按预期工作。
我不知道发生了什么,也许outStream.isDone()调用尝试将boolean复制到新的内存地址,并且无情的轮询不允许它。
请分享您在此问题上的经验和知识。
答案 0 :(得分:2)
在多线程环境中,当一个线程更改一个值应该对其他线程可见时,您需要可见性。对于您的情况,您可以使用volatile boolean flag
或使用AtomicBoolean
变量类型,以便其他线程可见当一个线程更改值时。
volatile boolean done = false;