2013-01-19 44 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.