2016-07-02 41 views
1

目前我正在嘗試構建一個蛇遊戲作爲我在java中的第一個項目,並且正在使用線程。我希望有一個對象在到達屏幕邊界時等待,然後在鍵輸入進入時繼續通知另一個方向。 在底部我調用notify()函數,但沒有任何反應,並且線程繼續處於wait()狀態。任何幫助將非常感激。java無法通知()線程?

package com.foreverblu.snake; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
public class snakeobject extends JPanel{ 
int x = 0; 
int y = 0; 
int z = 0; 
int a = 0; 
Thread animationThread; 
Thread notifyThread; 
public void paintComponent(Graphics g) { 

    super.paintComponents(g); 
    this.setBackground(Color.black); 
    g.setColor(Color.GREEN); 
    g.fill3DRect(x, y, 30, 30, true); 



} 
public void keepGoing() { 
    animationThread = new Thread(create); 
    notifyThread = new Thread(create2); 
} 
Runnable create = new Runnable() { 
    public void run() { 
     synchronized(this) { 
     while(z>=0 || z<=3) { 
      if(z==2 && y>0) { 
      y-=30; 
      repaint(); 
      try{Thread.sleep(500);} catch (Exception ex) {} 
      }else if(z==1 && y<=450) { 
       y+=30; 
       repaint(); 
       try {Thread.sleep(500);} catch (Exception ex) {} 
      }else if(z==0 && x<=450) { 
       x+=30; 
       repaint(); 
       try{Thread.sleep(500);} catch (Exception ex) {} 
      }else if(z==3 && x>0) { 
       x-=30; 
       repaint(); 
       try{Thread.sleep(500);} catch (Exception ex) {} 
      }else{ 
       notifyThread.notify(); 
      } 
     } 
     } 

    } 
}; 
Runnable create2 = new Runnable() { 
    public void run() { 
     synchronized(this) { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      try { 
       animationThread.wait(); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     do{try{Thread.sleep(500);} catch (Exception ex) {} 
     continue; 
     }while(a==0); 
     if(a==1) { 
     System.out.println("Notified"); 

     a=0; 
     animationThread.notifyAll(); 
     } 
    } 
    } 

}; 

} 

其他職業: package com.foreverblu.snake;

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class snakeframe extends JFrame{ 
int z = 0; 
snakeobject swag = new snakeobject(); 
public snakeframe() { 
    super("The Great Title"); 
    swag.keepGoing(); 
    swag.notifyThread.start(); 
    swag.animationThread.start(); 
    addKeyListener(new KeyAdapter() { 
     public void keyPressed(KeyEvent e) { 
      if(swag.animationThread.getState()==Thread.State.WAITING) { 
        swag.a=1; 
        System.out.println("Swag"); 

      } 
      if(swag.animationThread.getState()==Thread.State.RUNNABLE) { 
       System.out.println("RUNNABLE"); 
      } 
      if(e.getExtendedKeyCode()==e.VK_DOWN) { 
       swag.z=1; 

      }else if(e.getExtendedKeyCode()==e.VK_UP) { 
       swag.z=2; 
      }else if(e.getExtendedKeyCode()==e.VK_LEFT) { 
       swag.z=3; 
      }else if(e.getExtendedKeyCode()==e.VK_RIGHT) { 
       swag.z=0; 
      } 
     } 

    }); 
    add(swag); 
} 
} 
+1

嗯,你使用的等待一個/通知不正確。在一臺監視器上同步,但通知另一臺監視器。如果執行任何相關代碼,您應該會收到異常。你不需要使用額外的線程,因爲EDT和主線程就足夠了。 – Kayaman

+0

你提到這是你的第一個Java項目。我建議你先去掉線程,然後再去尋求更多的基本設計。多線程不是你應該開始的事情。 – Gima

回答

0

目前,我試圖建立一個蛇遊戲作爲我在Java中的第一個項目,並使用線程我。

你正在努力學習太多的東西在同一時間;

  • Java語言,
  • Java標準庫,
  • 搖擺,以及如何設計桌面GUI應用程序,
  • 線程如何工作,以及如何使用它們來你的優勢。

減速。一次帶一個。


我想有一個對象的等待,當它到達屏幕的邊框,然後被通知當一個鍵輸入進來的...

這聽起來不像一個線程。爲遊戲中的每個移動對象提供一個線程是一個非常有限的設計選擇,並且有一個線程根據其狀態聽起來像一個糟糕的設計(IMO)而等待不同的事情。例如,當蛇正在移動時,我不會編寫等待實時時鐘的線程(即調用sleep()),然後在處於某種其他狀態時等待按鍵按下。

已經有一個等待按鍵的線程:它被稱爲事件分派線程(EDT),它會在任何Swing程序中爲您自動創建。而且,如果您想等待時間(例如,在遊戲中爲物體設置動畫),那麼最好使用Swing Timer


你應該知道, Swing方法(例如,repaint())可能從EDT內調用。只有極少數可以從其他線程調用SwingUtilities.invokeLater()等。


o.wait()o.notify()o.notifyAll()方法是低級別的原語是指在一個非常特定的圖案來使用,以實現更高級別的同步類新。 Java標準庫已經在java.util.concurrent包中定義了許多有用的同步類。任何時候你認爲你想使用等待/通知,你應該首先檢查java.util.concurrent中是否有一些東西能夠爲你節省一些努力。

如果必須使用等待/通知,那麼你應該閱讀Oracle的「保護模塊」教程,並使用它,它是爲了使用方式:https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html