2016-07-02 3 views
1

現在、私はJavaの最初のプロジェクトとしてスネークゲームを構築しようとしており、スレッドを使用しています。私はオブジェクトが画面の境界に達すると待ってから、別の方向への移動を続行するためにキー入力が来たときに通知を受けたい。 最後に、notify()関数を呼び出しますが、何も起こりません。スレッドは引き続きwait()状態になります。どんな助けでも大歓迎です。Javaスレッドがnotify()スレッドに通知できませんか?

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(); 
     } 
    } 
    } 

}; 

} 

他のクラス: パッケージ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

まあ、1のためにあなたは待機を使用しています/誤って通知します。 1台のモニターで同期するが別のモニターに通知する。関連するコードが実行されると、例外が発生するはずです。 EDTとメインスレッドで十分であるため、余分なスレッドを使用する必要はありません。 – Kayaman

+0

最初のJavaプロジェクトとしてこれを行うことに言及します。私はあなたがスレッドを廃止し、より基本的なデザインを先に進めることをお勧めします。マルチスレッドはあなたが最初にやるべきことではありません。 – Gima

答えて

0

現在、私はJavaでの私の最初のプロジェクトとしてヘビのゲームを構築しようとしていますし、スレッドを使用しています。

あなたは同時に多くのことを学ぼうとしています。

  • Java言語、スレッドがどのように動作するか
  • Javaの標準ライブラリ、
  • スイング、そしてどのようにデスクトップGUIアプリケーションを設計するには、
  • 、そしてどのようにあなたの利点にそれらを使用します。

スローダウン。一度に1つずつ取り出してください。以下のような音はありません、私はそれが画面の境界に到達したときにオブジェクト待機を持ちたい、その後、キー入力が入ってくるときに通知さ


...

スレッド。ゲーム内の各移動オブジェクトにスレッドを割り当てることは非常に限定的な設計選択であり、その状態に応じて異なるものを待つスレッドが悪いデザイン(IMO)のように聞こえることがあります。例えば、私は、スネークが動いているときにリアルタイムクロック(すなわち、sleep()を呼び出す)を待つスレッドをコード化せず、ある他の状態のときにキーを押すのを待つ。

すでにキープレスを待機しているスレッドがあります。イベントディスパッチスレッド(EDT)と呼ばれ、どのSwingプログラムでも自動的に作成されます。また、時計を待ちたい場合(ゲーム内のオブジェクトをアニメートするなど)、Swing Timerを使用する方がよいでしょう。


あなたは最も Swingメソッドは、(例えば、repaint())かもしれのみがEDT内から呼び出されることに注意する必要があります。他のスレッドから呼び出される可能性があるのはごくわずかです(SwingUtilities.invokeLater()など)。


o.wait()o.notify()o.notifyAll()方法は、より高いレベルの同期classessを実装するために、非常に特定のパターンで使用されることを意図されている低レベルプリミティブです。 Java標準ライブラリは、すでにjava.util.concurrentパッケージにいくつかの有用な同期クラスを定義しています。待機/通知を使用したいと思うときは、まず、java.util.concurrentに何か努力を惜しまないものがあるかどうかを確認する必要があります。

あなたは必見使用待機/通知した場合、あなたは、Oracleの「保護されたブロック」のチュートリアルを読んで、それをそれが使用されることを意図された方法を使用する必要があります。https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

関連する問題