1

ゲームを作成するためのベースとなる単純なアプレットを作成しましたが、すでに CPU の 50% を使用しています。私は 1.5GB の RAM を搭載した 3GHz の P4 を使用しているので、それほど消費しないはずです。

import java.awt.*;
import java.applet.*;

public class applettest extends Applet implements Runnable {

    long lastFrame;

    public void init() { 
        (new Thread(this)).start();
    }

    public void paint(Graphics g) {
        g.drawString("Welcome to Java!!", 50, 60 ); 
    }

    public void run() { 
        while(true) {
            // code here
            repaint();

            try{
                // wait 16 milliseconds to cap frame rate to 60 fps
                while (System.nanoTime() < lastFrame + 160000000)       {
                    Thread.yield();
                }

                lastFrame = System.nanoTime();
            }

            catch(Exception e){}
        }
    }
}
4

6 に答える 6

8

忙しい待機を次のように置き換えてみてください

lastFrame = System.currentTimeMillis();

while(true) 
{
   repaint();

   long msSleep = 16 - (System.currentTimeMillis() - lastFrame);
   lastFrame = System.currentTimeMillis();

   if(nsToSleep > 0)
   {
      Thread.sleep(msSleep);
   }
   else
   {
      Thread.yield();  // Only necessary if you want to guarantee that
                       // the thread yields the CPU between every frame
   }
}

これにより、フレーム間の時間が少なくとも 16ms であることが保証されます。レンダリング時間が 16 ミリ秒未満で、CPU を占有する他のスレッドがない場合、60 fps で実行されます。

元のソリューションでは 16 ミリ秒の最小値が強制されますが、必要な時間が経過するまで (CPU を使用する) システム時間を何度も ポーリングし続ける必要があります。

ノート:

于 2009-04-06T22:11:02.147 に答える
5

申し訳ありませんが、この投稿は直接的な回答というよりも「詳細については...」タイプであり、現在提供されていると思います-コメント内で物事が失われないようにすることが役立つと思いました。

このスレッドは、Thread.sleep() や Thread.yield() などのメソッドが実際に何をするかについて、多くの (確かに典型的な) 誤解を示しているようです。私は以前、これらの問題のいくつかを解決しようとしたところで、人々が興味深いと思うかもしれないいくつかの資料を書きました: Thread.sleep() (さまざまな負荷レベルでの動作のグラフを含む)、Thread.yield()および- -関連して、ここでは言及されていませんが、スレッドの優先度に関する私の見方に興味があるかもしれません。

ちなみに、この場合System.nanoTime() を使用しても通常はメリットはありません。どのような場合でも、最も近いミリ秒に丸められた時間を取得するだけです。厄介な計算とナノ秒のクロック時間を取得するための潜在的なオーバーヘッドを節約し (後者もそれほど悪くはありません)、古き良き伝統的な System.currentTimeMillis() を使用するだけです。スレッドがオーバースリープした場合は、次回はスリープを少なくして埋め合わせてください。

于 2009-04-07T05:45:36.343 に答える
2

時間が特定のしきい値に達するまで、忙しい待機をしています。ただし、譲歩は、他のスレッドが時間を必要としていない場合にスレッドの実行が停止することを意味するものではありません...

待機して CPU 使用率を削減したい場合は、Thread.sleep を検討してください。

于 2009-04-06T22:12:34.293 に答える
1

1600000 ns = 1.6 ms であることに注意してください。したがって、おそらく期待したほど長くスリープしていません。

于 2009-04-06T22:35:30.900 に答える
0

Thread.sleep とビジー待機の違いは、スレッドをスリープ状態にすると、x 秒間何もする必要がないことをコンピューターに伝え、PC は他のプロセスにその時間を使用さ​​せることです。

ただし、ビジー状態の待機では、実際には何も達成していない場合でも、ループ コードを常に実行するようにマシンに指示していることになります。

于 2009-04-07T05:26:36.747 に答える
-2

Java が CPU の 2 番目のコアを使用していないため、おそらく 50% しか表示されていません。

コードは、CPU と同じ速度で加算と比較を実行します。

// wait 16 milliseconds to cap frame rate to 60 fps
while (System.nanoTime() < lastFrame + 16000000)        {
  Thread.yield();
}

多くの計算を伴うきつい while ループの代わりに Thread.sleep(16) を使用します。

于 2009-04-06T22:11:43.190 に答える