2012-04-25 8 views
0

私は自分のプロジェクトに「ゲームエンジン」を書き込もうとしていますが、スレッドに問題があります。メインフローでスレッド(LoadThread)を作成すると、Run();まで待機します。 LoadThreadで終了します。メインスレッドは新しいスレッドを待っています

//loading thread 
public class LoadThread implements Runnable{ 
    private boolean running = false; 
    private Thread loader = null; 

    public LoadThread(/*init data structures*/){ 
     loader = new Thread(this); 
    } 

    public void start(){ 
     running = true; 
     run(); 
    } 

    synchronized public void run() { 
     System.out.println(" loading started "); 
     while(running){    
      //do some loading, when done, running = false 
     } 
     System.out.println(" loading done "); 
    } 
} 

//holds data, starts loading 
public class SourceGod { 
    private LoadThread img_loader; 
    public void startLoading(){ 
     img_loader = new LoadThread(/* some data structures */); 
     img_loader.start(); 
    } 
} 

//runs the game 
public class Game extends GameThread implements ActionListener{ 
    private SourceGod sources; 
    public Game(Window full_screen){ 
     sources = new SourceGod(/* some data structures */); 
     System.out.println("before"); 
     sources.startLoading(); 
     System.out.println("after"); 
    } 
} 

//own thread to refresh 
abstract public class GameThread extends JPanel implements Runnable{ 
    //anything from there is not called before "after" 
} 

出力

before 
loading started 
//some loaded data report, takes about 2-3s 
loading done 
after 

すべてのヘルプは理解されるであろう。 (コードhttp://paste.pocoo.org/show/orCfn9a8yOeEQHiUrgjG/のもう少し) おかげで、 Vojtěch

答えて

5

あなたの問題は、あなたのコンストラクタでThreadオブジェクトを作成しているが、あなたはstart()呼び出すときに、スレッドを開始するが、同じスレッドでrun()方法を実行していないということです。これは、の周囲に混乱しているように見えます。Threadを実装すると、Runnableを実装しています。私はあなたが代わりにやるべきだと思う何

ようなものです:

// this should be of type Thread not LoadThread 
private Thread img_loader; 
... 
// don't create the loader thread inside of LoadThread 
img_loader = new Thread(new LoadThread(/* some data structures */)); 
img_loader.start(); 

LoadThreadは、スレッドが実行されるタイプRunnableのクラスです。それが呼び出したときに、あなたの現在のコードでは、:

public void start(){ 
    running = true; 
    run(); 
} 

編集:

img_loader.start(); 

それは実際に新しいスレッドを起動していない、それだけで同じスレッドでrun()を呼び出すLoadThread.start()メソッドを呼び出しています:

あなたが提供したリンクの投稿コードをより詳しく見ると、あなたのThreadオブジェクトがLoadThread constrの中に作成されていますuctor。これは、良好なパターンではありません。だから、もう一度

public LoadThread(/*init data structures*/) { 
    // not recommended IMO 
    loader = new Thread(this); 
} 

、あなたがスレッドを開始が、同じスレッドでrun()を呼び出していないLoadThread.start()を呼び出しているとき。代わりにnew Thread(new LoadThread())パターンを使用します。あなたがLoadThreadの内部Threadをラップの上に立ち往生しているなら、あなたはするLoadThread.start()を変更する必要があります:あなたは別のスレッドでfalseにrunningを設定したい場合は

// this should be removed, you want to call Thread.start() instead 
public void start(){ 
    running = true; 
    // this will start the internal thread which will call run() 
    loader.start(); 
} 

ところで、それはvolatileとしてマークする必要があります。

0

あなたは、Runnableインタフェースを使用する方法にはいくつかの問題を抱えて:

  • 実行可能で、それは別のスレッドで起動できるようにコードをラップする方法です。 runメソッドをオーバーライドする必要があります。それを直接的に呼び出すことは決してありません。
  • 実行可能ファイルを使用してスレッドにラップし、スレッド開始メソッドを実行する。したがって、スレッドの開始メソッドをオーバーライドしたり、super.start()を常に呼び出すべきではありません。
  • runnableにstartメソッドを提供するのは面倒です。ラッピングスレッドのstartメソッドは、新しいスレッド(ラッパー1)でrunnableのrunメソッドを呼び出します。それでおしまい。したがって、実行可能なメソッド内にstartメソッドがある場合、ラッピングスレッドによって呼び出されることはありません。
  • スレッドまたは実行可能ファイルのいずれかのrunメソッドを呼び出してはいけません。メソッドが現在のスレッドで実行され、新しいスレッドでは実行されないため、この点を逃してしまいます。
  • 実行メソッドを同期させません。既に1つのスレッドのみが使用することを意図しています。ご覧のとおり、あなたがstartメソッドを使用する場合は

    //loading thread 
    public class LoadThread implements Runnable{ 
        /** Wether or not the thread is running. */ 
        private boolean running = false; 
        /** Wrapper thread. */ 
        private Thread loader = null; 
    
        public LoadThread(/*init data structures*/){ 
         loader = new Thread(this); 
        } 
    
        public void start(){ 
         running = true; 
         loader.start(); 
        } 
    
        @Override 
        public void run() { 
         System.out.println(" loading started "); 
         while(running){    
          //do some loading, when done, running = false 
         } 
         System.out.println(" loading done "); 
         running = false; 
        } 
    } 
    

    、単なるラッパースレッドのstartメソッドを呼び出します。ここでは

は、あなたの場合には何をすべきかです。

あなたが本当にスタートを呼び出す必要がある場合にも、直接実行可能しかし、スレッドを使用していない考慮が:

//loading thread2 
public class LoadThread extends Thread{ 
    /** Wether or not the thread is running. */ 
    private boolean running = false; 

    @Override 
    public void run() { 
     running = true; 
     System.out.println(" loading started "); 
     while(running){    
      //do some loading, when done, running = false 
     } 
     System.out.println(" loading done "); 
     running = false; 
    } 
} 

はるかに簡単であること。

関連する問題