我写了一个简单的applet作为基础制作游戏,它已经占用了我50%以上的CPU.我正在使用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){}
}
}
}
Run Code Online (Sandbox Code Playgroud)
尝试更换你的忙等待与
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
}
}
Run Code Online (Sandbox Code Playgroud)
这将保证帧之间的时间至少为16ms.如果渲染时间小于16ms,并且没有任何其他线程占用CPU,则它将以60fps运行.
您的原始解决方案将强制执行最小16ms,但它必须反复轮询系统时间(使用CPU),直到经过必要的时间.
笔记:
repaint()是异步调用(即它会立即返回)对不起,这篇文章更多的是"和更多的信息..."类型,而不是直接的答案,我认为现在已经给出了 - 我只是认为不要让评论中的内容丢失是有帮助的.
这个线程似乎显示了很多(公认的)典型的误解,关于Thread.sleep()和Thread.yield()实际上做了什么.我之前写过一些人们可能会感兴趣的材料,我试图清除其中的一些问题:Thread.sleep()(包括不同负载级别下的行为图),Thread.yield()和 - - 相关虽然这里没有提到,人们可能会对我对线程优先级的看法感兴趣.
顺便提一下,在这种情况下使用System.nanoTime()通常没有任何好处:在任何情况下,你只需要将时间四舍五入到最接近的毫秒.我将保存您的笨拙计算和检索纳秒时钟时间的潜在开销(虽然后者也不是那么糟糕)并且只使用好的传统System.currentTimeMillis().如果您的线程处于睡眠状态,只需通过较少的睡眠进行补偿.