2011-07-11 5 views
5

all。私が取り組んでいるJavaプログラムのスレッドは、スペース内でランダムウォークをアニメートします(少なくとも、この問題は解決されます)。これには、次の2つの方法が含まれます。Java内のスレッド間の可変永続性に関する問題

public void run() { 
    while(gw.checkBoundingBox()) { 
     if(!gw.pause) step(); 
    }  
} 

public void step() { 

    Point3d p1, p2; 

    //get the last point, step, get the new point 
    p1 = new Point3d(gw.position); 
    gw.randomStep(); 
    p2 = new Point3d(gw.position); 

    //create the Alpha that will do the animation, and wrap it in an AlphaControl, 
    //which will set this object's pause flag until the Alpha finishes 
    Alpha alpha = new Alpha(); 
    alpha.setLoopCount(1); 

    if(alpha.finished()) System.out.println("DEBUG: I'm already dead."); 

    AlphaControl ac = new AlphaControl(alpha,gw); 
    ac.start(); 

    //create a piece of the path, attach an interpolator to do the animation 
    PathCyl cyl = new PathCyl(p1,p2); 

    StretchInterpolator si = new StretchInterpolator(alpha, cyl.anchor); 
    si.setSchedulingBounds(new BoundingSphere(new Point3d(0,0,0),50)); 
    cyl.anchor.addChild(si); 

    //put it all together 
    BranchGroup b = new BranchGroup(); 
    b.addChild(cyl.tg); 
    trans.addChild(b); 
} 

したがって、一時停止フラグが設定されていない場合は、手順()が実行されます。あなたが見る必要があるstep()の唯一の部分は、Alphaオブジェクトに関する数行です。 (Alphaは、アニメーション化に使用される時間依存関数を生成するAPIクラスです)。したがって、step()はAlphaオブジェクトを作成し、AlphaControlという別のスレッドに送ります。 AlphaControlは、このステップがアニメートされるまで、ポイントの計算を停止するようにプログラムに指示します。これは、run()メソッドでチェックされている一時停止フラグを設定することで行います。

だから何が問題なのですか? Alphaが作成された後でAlphaが終了したかどうかを直ちに確認するデバッグ行を追加しました。このコード行は決して実行しないようです。アルファは終了しましたか?もちろん、私たちはそれを作成しました。しかし、この行は、最初に関数が呼び出されるたびに実行されます。何とか同じAlphaインスタンスにぶら下がって何度も繰り返し使用しています。これは、AlphaControlスレッドでまだ生きているAlphaへの参照が原因であると考えています。

どうすればこの問題を解決できますか?私はいくつかのことを試みました。私は、アルファの膨大な配列を作成し、歩行が始まる前にそれらをすべて初期化し、すべてのステップで配列から異なるアルファを使用するように指示しようとしましたが、これは同じ結果でした。私はまた、AlphaControlを使ってアルファを閉じる前にnullに設定しようとしましたが、これはうまくいきませんでした。このオブジェクトを破壊することは可能ですか? step()コードが再び実行に戻るまでに、最初に作成されたAlphaControlを実行してガベージコレクションを待つ必要があります。

また、それを見て参考にしたい場合は、AlphaControlクラスをご覧ください。

public class AlphaControl extends Thread { 

public Alpha alpha; 
public GraphicalWalker gw; 

public AlphaControl(GraphicalWalker gw, Alpha alpha) { 
    this.gw = gw; 
    this.alpha = alpha; 
} 

public void run() { 

    boolean stop = false; 
    boolean finished; 

    while(!stop) { 
     finished = alpha.finished(); 

     if(!finished && !gw.pause) gw.pause = true; 
     if(finished && gw.pause) gw.pause = false; 
     if(finished) stop = true; 
    } 
} 

} 

ご協力いただきありがとうございます。 Jeff

+3

あなたは 'Alpha'のコードを表示しませんでした:' alpha.finished() 'が' alpha'を構築した直後に 'false'を返すことは確かですか?そして 'alpha.setLoopCount(1);'は 'false'にセットしませんか? – Howard

+1

Alphaのソースも参照すると役立ちます。 – nojo

+0

コードをデバッグしようとしましたか?そうでなければ一度してください。 –

答えて

0

私はプログラムの意図に完全に従っているかどうかはわかりませんが、競合状態にあるようです。 AlphaControlオブジェクトのac.start()を呼び出すと、はありません。は、ループ実行の次のラウンドの前にgw.pauseが設定されることを保証していません。実際には、gw.pauseが設定される前にループが何度も実行される可能性があります。

ちょうどキックのために、画像からスレッディングを取るためのショートカットとして、run-throughでac.run()を呼び出すことをおすすめします。意図した動作が発生した場合、私は単一のスレッドではなく複数のスレッドでこれを行う理由を厳しく見ていきます。

0

私はこの問題は、二つの問題の一つだと思い:

  • Alphaの状態は、それがAlphaのすべてのインスタンスに対して同じだということを意味し、静的変数として保持され、あなたはおそらくありませんねそれをコンストラクタでリセットします(正当な理由で)。
  • コンパイラがマークされフィールドは常に新鮮値のルックアップが必要になることを知っているに依存しているセマンティクスを破るvolatileをマークされていない、あなたの状態のいくつかの部分は、(そうでない場合、コンパイラは値をキャッシュするために自由である)
2

あなたのコードが失敗する理由を理解するための鍵は、Java3DライブラリのAlphaクラスが何をするのかを理解することです。 あなたの質問から、それが正しく理解されていないように思えます。 はループしません。ソースコード(http://www.java2s.com/Open-Source/Java/6.0-JDK-Modules/java-3d/javax/media/j3d/Alpha.java.htm)をチェックすると、単一のループ構造が含まれていないことがわかります。それがするのは、時間値を[0,1]の範囲の値にマップする関数を定義することです。

あなたが完成()メソッドのソースを見れば:

/** 
    * Query to test if this alpha object is past its activity window, 
    * that is, if it has finished looping. 
    * @return true if no longer looping, false otherwise 
    */ 
    public boolean finished() { 
     long currentTime = paused ? pauseTime : J3dClock.currentTimeMillis(); 
     return ((loopCount != -1) && 
      ((float)(currentTime - startTime) * .001f > stopTime)); 
    } 

あなたはそれが呼び出されたときにその値がに依存していることに気づきます。

基本的にアルファを1ミリ秒のループにするように定義しているので、アルファを作成してから1ミリ秒後には終了せず、それ以降は終了しません。

こちらがお役に立てば幸いです。

関連する問題