在一个间隔上运行一个while循环

时间:2012-08-06 19:33:11

标签: java

我正在建立一个非常注重物理学的游戏。因此我需要游戏以非常特定的间隔运行。目前的代码:

public double period = .02; //this is the run interval in seconds

//main gameLoop
public void gameLoop(){
    long startTime;
    long sleep;

    while(running){
        startTime = System.nanoTime();

        Graphics2D g = s.getGraphics();
        operateEntities(g);
        g.dispose();
        s.update();
        //figure out how long it must sleep to take .02s altogether
        sleep = ((int)(period*1000) - (System.nanoTime() - startTime)*100000);
        try{
            if(sleep > 0){
                Thread.sleep(sleep);
            }else{
                System.err.println("Warning: program runtime exceeded period");
            }
        }catch(Exception ex){}

        gameTime += period;
    }
}

这不按预期工作。目前主线程正在执行而根本没有休眠,并且“警告:程序运行时超出期限”警告正在触发。

以前我使用的是System.currentTimeMillis(),但是对于我的目的来说它不够准确,所以我切换到了System.nanoTime()

增加周期实际上可以加速程序,同时减少它会减慢它。

有一个简单的逻辑faw?是我对System.nanoTime()的理解了吗?或者是否有更好的方法来运行特定时间间隔的操作实体,处理和更新?

编辑:为了记录,该程序完成的时间不会超过.02秒。它已经过测试

2 个答案:

答案 0 :(得分:8)

纳秒小于毫秒,因此,转换纳米 - > millis,你必须除以100000,而不是多余的;

    //figure out how long it must sleep to take .02s altogether
    sleep = ((int)(period*1000) - (System.nanoTime() - startTime)*100000);

应改为

    //figure out how long it must sleep to take .02s altogether
    sleep = ((int)(period*1000) - (System.nanoTime() - startTime)/100000);

你当前的代码试图睡眠200ms减去一个大数字,使睡眠变为负数,并给你“警告:程序运行时间超过期限”输出

答案 1 :(得分:2)

分解你的代码有很多问题:

//Multiplies by 100,000 rather than divides.
sleep = ((int)(period*1000) - (System.nanoTime() - startTime)*100000);
//Note that sleep here is a very small number minus a very large number: probably negative.

try{
  if(sleep > 0){//If positive, sleep
    Thread.sleep(sleep);
  } else{//throws an error in all other cases.
    System.err.println("Warning: program runtime exceeded period");
  }
}catch(Exception ex){}//Empty exception handling poorly handles the thread.sleep() Exception requirement.

除非您使period值更大,否则此代码将始终出错。然而,即使超出此范围,您的方法也不可能产生您想要的结果:准确的计时。你的核心循环是什么:

  • 计算物理0.02秒。
  • 去睡觉。
  • 检查现在几点。
  • 如果已经过了特定时间段(0.02秒),请继续,否则再次入睡。
  • 重复。

如果时间片足够小,这将是准确的。但是,线程不能像那样工作。你无法保证线程什么时候醒来。它可能永远不会。可能会在三秒钟内完成。它可能是即时的。无论你的时间段是什么,你都有可能超越你,你将永远不会辜负它。

您需要在实际经过的时间段内扩展所有物理,而不是依赖于每次都经过的特定时间段,而不是依赖于特定的增量周期。

  • 去睡觉。
  • 了解已经过了多长时间。
  • 计算该时间段的物理。
  • 重复。

您仍然需要一个小的时间片来休眠,但这样就可以消除线程调度程序引入的错误。