1

単純なゲームをコーディングしているときに、奇妙な動作を経験しました。基本的に、ゲーム内で数秒ごとにイベントを発生させる無限ループのスレッドを作成します。Sysout(runAnimation)を配置すると、すべてが正常に機能します。ただし、削除するとすぐに発生しなくなります。

system.out calllがプログラムの動作に影響を与えているようですが、なぜこれが発生する可能性があるのか​​、誰かが知っていますか?

ループは次のとおりです。

private void run(){
            long lastTime = -1;
            while(true){
                int timePerStep = (int) Math.ceil(ANIM_TIME/frequency);
                System.out.println(runAnimation);
                if(runAnimation && System.currentTimeMillis() - lastTime > timePerStep){
                    lastTime = System.currentTimeMillis();
                    controller.step();
                    try {
                        Thread.sleep(timePerStep);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
    }

それは私のクラスの構築中に次のように開始されました:

animThread = new Thread(new Runnable() {
            @Override
            public void run() {
                GUIView.this.run();
            }
        });
animThread.start();
4

2 に答える 2

4

System.out.println()呼び出しはsynchronized(ほとんどのメソッドPrintWriter呼び出しは)なので、コード内で同期していないものがあると思われます。畑が気になりrunAnimationます。別のスレッドで設定されている可能性がありますか?多分それはする必要がありますvolatileか?あるスレッドで変更され、別のスレッドで読み取られるフィールドは、synchronizedまたはである必要がありますvolatile同期に関するJavaスレッドのチュートリアルを読むと役立つ場合があります。

コードをもっと見ることなくして、それに指を置くのは難しいですが、とにかくこの答えが役立つと思います。

最後に、本当にスレッドが回転するまでスレッドを回転runAnimationさせたいですtrueか?それは非常に悪い習慣です。もしそうなら、たぶんあなたはループの中でしばらく眠るべきrunAnimationですfalse。もう1つのアイデアは、CountDownLatchまたは他のシグナリングメカニズムを使用して、アニメーションを実行する必要があるまでスレッドを一時停止することです。

于 2013-01-19T19:10:22.990 に答える
0

フィールドが揮発性でない場合、JITはフィールドが変更されていないと見なして、レジスターに配置したり、コードにインライン化したりすることができます。このタイトなループにシステムコールを配置すると、

  • スレッドがフィールドを変更するかどうかについて推測できないため、JITがこの方法でコードを最適化するのを防ぎます。
  • ループを遅くして、10,000回実行されないようにします(これは、JITが開始するポイントです)

詳細については、Javaメモリモデルと最適化について書いた記事をご覧ください。

于 2013-01-20T09:26:35.260 に答える