我更改了一个值,用于确定while循环何时在单独的线程中终止。
我不想知道如何使这个工作。如果我只通过synchronized getters / setters访问变量测试,它会按预期工作..
我原以为,如果某些读/写命令由于并发而丢失,程序有时不会终止,但永远不会。这让我感到困惑..
我想知道为什么程序从不终止,没有print-command。我想了解为什么print-command会改变任何东西..
public class CustomComboBoxDemo {
public static boolean test = true;
public static void main(String[] args) {
Thread user =new Thread(){
@Override
public void run(){
try {
sleep(2000);
} catch (InterruptedException e) {}
test=false;
}
};
user.start();
while(test) {
System.out.println("foo"); //Without this line the program does not terminate..
}
}
}
答案 0 :(得分:8)
最可能的解释是变量只读一次,将while
变为无限循环(或无操作)。由于您尚未将test
声明为volatile
,因此允许编译器执行此类优化。
从循环内部调用外部函数后,编译器无法再证明test
在循环迭代中保持不变,并且不执行优化。
答案 1 :(得分:1)
如果test
变量未定义为volatile
,则编译器可能会将不包含任何操作的循环优化为主线程的while(true)
循环,并且程序永远不会结束。
否则,实际检查test
变量的值,当第二个线程更改其值时,主线程将离开while
循环并且程序终止。
答案 2 :(得分:0)
我认为这与处理IO的方式有关。没有打印,你可能会看到使用所有可用CPU时间的java应用程序;对于打印,IO延迟可能会占用足够的CPU时间来进行其他处理。
测试这个理论的一种快速方法是将printlns放在线程的run()方法中,以查看线程是否实际执行。根据我的经验,无限的空循环会导致许多奇怪的行为。
那就是说,它似乎在我的工作站上在JDK 1.6.0_10_b23
下终止答案 3 :(得分:0)
好像你的循环被错误地编译成忙碌的等待。在布尔值中添加volatile关键字可以纠正“问题”。
答案 4 :(得分:0)
public static boolean test = true;
public static void main(String[] args) {
Thread user =new Thread(){
@Override
public void run(){
try {
sleep(2000);
} catch (InterruptedException e) {}
test=false;
System.out.println("Thread.end <"+test+">");
}
};
user.start();
while(test);
}
这很有趣。编译器最有可能在进入无限循环时优化它,而不是在每个循环中读取值。
将测试定义为volatile可解决此问题并让您的程序终止
顺便说一句:你可能已经知道你应该使用user.join()来等待线程结束答案 5 :(得分:0)
我不明白您尝试使用您知道未正确同步的代码。
有些人报告说,在他们的机器上,代码的行为与机器上的行为不同。严重同步代码的行为是未定义。尝试理解它的作用是没有意义的,因为该行为将随JVM版本或体系结构而改变。