2013-01-19 18 views
1

我在编写简单的游戏时遇到了奇怪的行为。基本上,我创建了一个无限循环的线程,每隔几秒就会在游戏中触发一个事件。随着Sysout(runAnimation)到位,一切正常。然而,只要我删除它甚至停止发生。Heisenbug:线程不运行没有sysout

看来,System.out的calll是影响程序的行为,没有任何人有一个想法,为什么这可能发生

这里是循环:

private void run(){ 
      long lastTime = -1; 
      while(true){ 
       int timePerStep = (int) Math.ceil(ANIM_TIME/frequency); 
       System.out.println(runAnimation); 
       if(runAnimation && System.currentTimeMillis() - lastTime > timePerStep){ 
        lastTime = System.currentTimeMillis(); 
        controller.step(); 
        try { 
         Thread.sleep(timePerStep); 
        } catch (InterruptedException e) { 
         Thread.currentThread().interrupt(); 
        } 
       } 
      } 
    } 

它在开始我班的建设如下:

animThread = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       GUIView.this.run(); 
      } 
     }); 
animThread.start(); 

回答

4

System.out.println()呼叫​​(最PrintWriter方法调用AR e)所以我怀疑你的代码里面没有同步的东西。我想知道runAnimation字段。难道它是在另一个线程中设置的?也许它需要是volatile?在一个线程中修改并在另一个线程中读取的任何字段都需要为​​或volatile。阅读Java thread tutorial around synchronization可能会有所帮助。

没有看到更多的代码,很难指责它,但我怀疑这个答案无论如何将有所帮助。

最后,你真的你的线程直到runAnimationtrue?这是一个非常糟糕的做法。如果runAnimation也是false,也许你应该在循环中睡一段时间。另一个想法是使用CountDownLatch或其他信号机制来暂停您的线程,直到它需要执行动画。

0

如果您的字段不是易失性的,那么JIT可以认为它不会更改并将其放入寄存器中,甚至可以将其内嵌到代码中。在这种紧密的循环放置一个系统调用可以

  • 防止JIT优化从代码这种方式,因为它不能对线程是否修改场假设。
  • 减慢循环,因此不会运行10000次(这是其在JIT踢点)

有关详细信息,这里是我关于这个问题写了一篇文章Java Memory Model and optimisation.