2013-07-02 57 views
0

因此,我正在製作這個Java小程序,我只是想先確保鍵輸入正常工作,然後再使它更復雜。我不知道爲什麼,但是當你刪除「System.out.print(needUpdating);」它不能根據鍵輸入正確地移動矩形。有誰能告訴我爲什麼以及如何解決它?這對我來說是個謎。布爾沒有正確更新,除非你打印它

import java.applet.Applet; 
import java.awt.Graphics; 
import java.awt.Rectangle; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener;  
import javax.swing.JApplet;  

public class firstApplet extends JApplet implements KeyListener, Runnable { 
    final int MOVEAMOUNT = 1;  
    boolean needUpdating;  
    int x,y,dx,dy;  
    Thread runner = null; 

    public void init() { 
     this.setFocusable(true);    
     needUpdating = false;   
     this.requestFocusInWindow();    
     x=0;    
     y=0;    
     dx=0;   
     dy=0;   
     addKeyListener(this); 
    } 

    public void stop() {    
    } 

    public void start() { 
     runner = new Thread(this);   
     runner.start(); 
    } 

    public void paint(Graphics g) { 
     System.out.println("x= "+x+" y = "+y);   
     g.drawRect(x, y, 100, 15); 
    } 

    @Override 
    public void keyPressed(KeyEvent e) {       
     int key = e.getKeyCode();   
     if(key==KeyEvent.VK_UP) { 
      System.out.println("up"); 
      dy=MOVEAMOUNT; 
     } 
     else if (key==KeyEvent.VK_DOWN) { 
      dy=-MOVEAMOUNT; 
     } 
     else if (key==KeyEvent.VK_LEFT) { 
      dx=-MOVEAMOUNT; 
     } 
     else if (key==KeyEvent.VK_RIGHT) { 
      dx=MOVEAMOUNT; 
     } 
     // TODO Auto-generated method stub   
     needUpdating = true;    
     System.out.println("needUpdating listening = " +needUpdating); 
    } 

    @Override 
    public void keyReleased(KeyEvent e) { 
     // TODO Auto-generated method stub 
     dx=0; 
     dy=0; 
    } 

    @Override 
    public void keyTyped(KeyEvent e) {   
    } 

    public void processMovement() { 
     System.out.println("processing"); 
     x+=dx; 
     y+=dy; 
    } 

    @Override 
    public void run() { 
     this.addKeyListener(this); 
     while(true) { 
      System.out.print(needUpdating);    
      if(needUpdating) { 
       processMovement();     
       repaint();     
       needUpdating=false; 
      }   
     }   
    } 
} 
+0

嘗試使'needUpdating'字段具有揮發性:'volatile boolean needUpdating;' – Andremoniy

回答

5

您的代碼被錯誤地同步。最好說,它根本不同步。然而,System.out.println是一種同步方法,並且在當今典型的CPU體系結構中,輸入同步塊碰巧在本機代碼級被實現爲內存屏障。這具有使對其他線程可見的布爾變化的效果。

結論:正確地同步你的代碼和「神奇」的行爲會消失。

+0

我修正了這些錯誤,發現當你按下箭頭時矩形會上升。 – johnchen902

+1

這並不令人驚訝,因爲在這種情況下減少了'y',座標系的原點在左上角。 –

1

你必須讓你的領域needUpdatingvolatile

volatile boolean needUpdating;

此行爲是由無限循環中run()方法定義:JVM緩存needUpdating領域的價值。

UPD:我只是檢查你的代碼:它工作正常volatile修飾符現場needUpdating,所以我的答案是解決方案。

UPD2:爲了澄清這個問題,看看例子JLS7的第17章:17.3. Sleep and Yield

4

沒有與此代碼的嚴重問題。首先你沒有很好的理由實現Runnable。其次,你的run()方法是一個很大的忙等待循環。第三,當然,您的needsUpdating變量缺乏同步。

您應該在偵聽器方法中執行所需的操作,而不是使用線程不安全的needsUpdating變量,並且線程安全問題將會消失,因爲您將處於事件調度線程中。