我写了一个简单的小程序作为制作游戏的基础,它已经耗尽了我的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){}
}
}
}
答案 0 :(得分:8)
尝试用
替换busy waitlastFrame = 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),直到经过了必要的时间。
备注:强>
repaint()
是异步调用(即it will return immediately)答案 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循环。