以下是我认为不遵循代码应该执行的代码片段:
public void updateTimeElapsed() {
timeElapsedLabel.setText("Time elapsed: " + ((System.nanoTime() - time) / Math.pow(10, 9)));
}
public void updateTimeElapsedIndefinitely() {
while (true) {
//System.out.println("Hi");
//TODO: Why this no work?
if (start) { System.out.println("Shoulda'"); updateTimeElapsed(); }
}
}
如果我评论
System.out.println("Hi")
代码显然不起作用。 如果我取消注释它,那就确实了!
注意: 按“s”开始游戏时,start就为真。 但是,该方法在开始时被调用,因此“hi”应该多次显示并且无限期地显示,直到我按下's'键。
一张图片说千言万语,所以我会给你数百张图片(视频)来解释我的意思: https://dl.dropbox.com/u/2792692/CodeWeird.ogv
https://dl.dropbox.com/u/2792692/CodeWeird.wmv
有谁能告诉我发生了什么事?
答案 0 :(得分:7)
看起来布尔start
正在被另一个线程更新,但您没有将其声明为volatile
,因此循环永远不会查看更新后的值。
通过添加println“修复”它只是JVM在获取控制台打印机的本机系统对象时管理线程堆栈状态的方式的一个可怕后果。解决方法是启动volatile和/或同步访问它。
SCCE:
永不打印:
public class Testit {
public static void main(String[] args) {
busted t = new busted();
t.start();
try {
Thread.sleep(1000L);
} catch (Exception e) {}
t.startUpdating();
}
public static class busted extends Thread {
private boolean start = false;
public void startUpdating() {
start = true;
}
@Override
public void run() {
updateTimeElapsedIndefinitely();
}
public void updateTimeElapsedIndefinitely() {
while (true) {
if (start) {
System.out.println("Hello");
}
}
}
}
}
通过更改为:
,在1秒钟后开始发送垃圾邮件 private volatile boolean start = false;
答案 1 :(得分:2)
我认为Affe想法是好的,但我想建议你在将来尝试使用Timer而不是while(true)循环。至少在我看来这要好得多。