这是我认为不遵循应执行的代码的代码段:
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就为true。但是,该方法在一开始就被调用,因此应多次无限制地显示“ hi”,直到按“ s”键为止。
图片说出一千个单词,所以我给你数百张图片(视频)来解释我的意思:https : //dl.dropbox.com/u/2792692/CodeWeird.ogv
https://dl.dropbox.com/u/2792692/CodeWeird.wmv
谁能告诉我发生了什么事?
看起来布尔值start正在由另一个线程更新,但是您没有将其声明为volatile,因此循环永远不会查看更新后的值。
start
volatile
通过添加println来“修复”它只是JVM在为控制台打印机获取本机系统对象时管理线程的堆栈状态的一种方式的后果。解决方法是使启动不稳定并/或在访问它时进行同步。
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秒钟后开始向您发送垃圾邮件Hello:
private volatile boolean start = false;