为什么这个简单的小程序使用了大约50%的CPU?

时间:2009-04-06 22:03:12

标签: java applet cpu

我写了一个简单的小程序作为制作游戏的基础,它已经耗尽了我的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){}
        }
    }
}

6 个答案:

答案 0 :(得分:8)

尝试用

替换busy wait
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 。如果渲染时间小于16ms,并且没有任何其他线程占用CPU,则它将以60fps运行。

您的原始解决方案将强制执行最小16ms,但必须一直保持polling系统时间(使用CPU),直到经过了必要的时间。

备注:

答案 1 :(得分:5)

很抱歉,这篇文章更多的是“和更多信息...”类型,而不是直接的答案,我认为现在已经给出了 - 我只是认为在评论中丢失内容是有帮助的。< / p>

这个线程似乎显示了许多(不可否认的典型)对Thread.sleep()和Thread.yield()实际执行的方法的误解。我之前写过一些人们可能会感兴趣的材料,我试图清除其中的一些问题:Thread.sleep()(包括不同负载水平下的行为图),Thread.yield()和 - - 相关虽然这里没有提到,人们可能会对我thread priorities的看法感兴趣。

顺便说一下,在这种情况下使用System.nanoTime()通常没有任何好处:在任何情况下,你只需要将时间四舍五入到最接近的毫秒。我将保存您的笨拙计算和检索纳秒时钟时间的潜在开销(虽然后者也不是那么糟糕)并且只使用好的传统System.currentTimeMillis()。如果您的线程过度睡眠,只需通过较少的睡眠进行补偿。

答案 2 :(得分:2)

你正忙着等到达到某个阈值的时间。但是,如果没有其他线程想要时间,屈服并不意味着你的线程停止运行......

如果您想等待并减少CPU使用,请考虑Thread.sleep

答案 3 :(得分:1)

请注意,1600000 ns = 1.6 ms,因此您可能没有达到预期的时间。

答案 4 :(得分:0)

Thread.sleep和忙碌等待之间的区别在于,当您将线程置于休眠状态时,您告诉计算机您不需要执行任何操作x秒,并且pc会让其他进程使用该时间。

然而,在忙碌的等待中,你告诉你的机器不断运行循环代码,即使它没有真正完成任何事情。

答案 5 :(得分:-2)

由于java没有使用CPU的第二个核心,你可能只看到50%。

您的代码将尽可能快地执行添加和比较。

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

使用Thread.sleep(16)代替具有大量数学运算的紧for循环。