while 循环还是 Thread.sleep()?

while loop or Thread.sleep()?

我正在 Java 编写游戏,我将 FPS 限制为 60。我想出了 2 种不同的方法来获得相同的结果,但我想知道其中哪一种是 better/cleaner 的方法。或者你有不同的想法。

while(System.nanoTime() - thisFrame < fps_limit);

Thread.sleep(sleepingTime);

我的想法是 while 循环Thread.sleep 对 CPU 的影响更大,对吗? ?

在此先感谢您的帮助!

Dom

你是对的,虽然两者都实现了你想要做的事情,while 循环将保持处理器被占用,消耗 CPU 时间。

相比之下,Thread.sleep() 释放处理器达到上述时间。

所以,Thread.sleep() 更好。

我同意@ayush - 虽然循环通常是阻塞函数,而线程更像是中断驱动或并行编程函数。我对 Java 有点不适应,但你能不能设置一个定时器而不是休眠?

是的,看起来像 C++ 中的 Timer 结构是可用的。看看这个:Timer in Java Thread

已经发布的两个答案都很好 - 睡眠比循环好。但是,您可以更详细地了解如何编写良好的循环。如果您有兴趣,这里有一个很好的资源:http://www.java-gaming.org/index.php?topic=24220.0

它涵盖了可变时间步长和插值等主题,可用于使您的图形运行极其流畅。这解决了 Thread.sleep 的时间不是 100% 准确的问题,并且如果您的游戏执行某些计算需要一些时间,则可以防止您的图形出现抖动。

您有以下主要选择:

  1. While loop - 这将消耗 CPU 个周期,并且通常实际上会停止系统,因为当你在循环时,其他线程不能 运行(在单核机器)。
  2. Thread.sleep() - 这可能有效,但您需要记住,不能保证等待指定的时间。
  3. DelayQueue - 更新。 Better/accurate 计时。
  4. ScheduledThreadPoolExecutor - 仍然比 DelayQueue 更新。使用 Thread Pool.

你不应该使用它们。请查看 ScheduledThreadPoolExecutor

的文档

特别是你在看这个函数

ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit)

我会做什么(伪代码)。

//timepast since last loop in ms
timepast = 0
fpslimit = 60
finished = true;
//while the game is running
while(runnning)
{
    timepast += timeSinceLastrun
    if(timepast  > 1second/fpslimit && finished)
    {            
            finished = false    
            dostuff(timepast)
    }
    //sleep for the time of 1second/fpslimit - timepassed to avoid cpu blocking
    Thread.sleep((1second/fpslimit) - timepast )
}

dostuff(deltatime)
{
   //do stuff in the end after it finished set 
   //finished to true so dostuff can be called again
   finished = true
   timepast=0
}

通过这种方式,您可以轻松地使用变量限制 fps,而无需阻塞其他线程。

正如 OldCurmudgeon 所说 thread.sleep 不阻塞 java 中的其他线程并使处理器时间可用。

Thread.sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system

您还可以将过去的时间作为 deltatime 传递给 dostuff 方法,这样游戏在所有设备上运行相同(相同速度)。

while loop 将使用 CPU 资源,只有当您的 avg.waiting 时间非常少并且期望精度时,它才有用。

Thread.sleep() 如果不期望精度则很好,因为 CPU 优先级会在线程唤醒后改变,它可能会或可能不会被安排立即到 运行 并且它也不应该像这样使用

while(! canContinue()) {
   Thread.sleep(1000);
}

对于上述情况,如果您想挂起当前线程并等待另一个线程处理某些事情,那么这些情况最好使用 wait()/notify()然后通知当前线程继续。

一些您可以阅读的参考资料,

http://tutorials.jenkov.com/java-concurrency/thread-signaling.html

http://www.jsresources.org/faq_performance.html#thread_sleep