而在多线程popgram中,即使满足条件,循环也不会在java中结束
我有一个多线程程序,它在某种情况下表现出奇怪的行为。由于专有问题,我不能在这里发布完整的代码,但我将示例错误放在这里 我有一个类,它有一个布尔变量,正在扩展Java线程类而在多线程popgram中,即使满足条件,循环也不会在java中结束,java,multithreading,Java,Multithreading,我有一个多线程程序,它在某种情况下表现出奇怪的行为。由于专有问题,我不能在这里发布完整的代码,但我将示例错误放在这里 我有一个类,它有一个布尔变量,正在扩展Java线程类 public class SystemStreamCapture extends Thread { InputStream is; boolean done = false; List<String> buffer; private final static Logger Log
public class SystemStreamCapture extends 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;
}
}
公共类SystemStreamCapture扩展了线程{
输入流为;
布尔完成=假;
列表缓冲区;
私有最终静态记录器Log=Logger.getLogger(SystemStreamCapture.class);
公共系统流捕获(InputStream为){
this.is=is;
}
公开募捐{
试一试{
InputStreamReader isr=新的InputStreamReader(is);
BufferedReader br=新的BufferedReader(isr);
字符串行=null;
而((line=br.readLine())!=null){
this.buffer.add(行);
}
br.close();
isr.close()
}捕获(ioe异常ioe){
日志错误(ioe);
}最后{
this.done=true;
}
}
公共列表getData(){
返回此.buffer;
}
公共布尔isDone(){
归还这个。完成;
}
}
此线程在其他类中使用,如下所示:
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();
}
公共类文件读取器{
私有最终静态记录器Log=Logger.getLogger(FileReader.class);
公共列表读取行(FileLineRequestModel请求)引发IOException{
String[]script={“/bin/sh”,“-c”,request.getCommand()};
调试(“执行行提取命令:+request.getCommand());
进程p=Runtime.getRuntime().exec(脚本);
SystemStreamCapture errStream=新的SystemStreamCapture(p.getErrorStream());
SystemStreamCapture outStream=新的SystemStreamCapture(p.getInputStream());
errStream.start();
outStream.start();
而(!outStream.isDone()){
//继续循环
//调试(“读取…”);
}
返回outStream.getData();
}
奇怪的部分是后一个类中的while循环。尽管“done”变量变为“true”,但循环永远不会结束。我还尝试了语法“(outStream.isDone()==false)
”,只是为了看看它是否有任何区别(我知道不会)。
然而,只要我在while中打开“Log.debug”(“reading…”)
”,它就会正常工作
我不知道发生了什么,可能是outStream.isDone()调用试图将布尔值复制到新的内存地址,而无情的轮询不允许这样做
请分享您在这个问题上的经验和知识。在多线程环境中,当一个线程更改时,您需要可见性。一个值应该对其他线程可见。对于您的情况,您可以使用
volatile boolean标志
或使用AtomicBoolean
变量类型,这样当一个线程更改时,它对其他线程可见更改值
volatile boolean done = false;
不看那堆代码,有一条规则:在
finally
语句中关闭流,或者使用try-with-resources。您是否查看文档以了解如何读取getErrorStream
?检查它是否仍然可用()您未使用的。有关详细信息:使完成易失性。尝试将完成标记为易失性。并且为了使其线程安全而不必同步,可能会更改为原子布尔
。请编辑您的答案,以显示哪个变量应该是易失性。谢谢有帮助。@vaibhav singh,如果你认为它对你有用,那么就投票吧,这样对其他人也会有帮助。