如何在循环中以完全相同的时间间隔调用方法?

时间:2014-01-03 12:15:15

标签: java time fixed

在Java中,我有一个调用方法的循环,然后该方法有一个sin,它将自执行程序以来的时间作为参数。此循环以每秒60次更新的速度运行(预期变化为+ -1或2次)。我想要做的是在该循环中调用一个方法,但该方法必须每0.2,0.4 ......秒(固定间隔)调用,所以我做的是:     if(executionTime % 200 == 0) 但这还不够,因为它并不总是准确,因此它会跳过很多次。就此而言,我尝试if(executionTime % 200 <= 50)尝试限制它,但它仍然跳过几次,但比以前少了。所以我的问题是,如果有任何方法让它在0.2秒完全运行,具有以下细节:

  • 如果循环在一次迭代中花费的时间超过0.2秒,则调用该方法。
  • 如果花了不到0.2秒,我不确定,因为如果它是30毫秒,那么显然不是,但如果它是198毫秒,那么是,在很小的范围内。

我正在使用的是使用每次调用方法时增加某个数字的变量调用sin(这是必须每200 ms调用一次的方法)。 Essentialy我想做一些类似于绘制一个依赖于时间(X)的函数的东西,其中X每循环迭代每200毫秒递增相同的数字。因此,每次循环迭代时,每200 ms计算一个新的图形点。我能做的是在每次调用循环内的其他方法之前检查是否有时间调用此方法,但这会破坏循环的顺序。我一直在搜索,但我只能找到调度,我认为这不会做。

编辑:伪代码:

int increment;

while(running){
    first();
    second();

    if(condition)
        doSomething();
    if(timeCheck) // time check every 200ms; this is what I don't know how to do
        graphfunction(increment);
}

3 个答案:

答案 0 :(得分:2)

我会使用java.util.concurrent的{​​{1}}。看看Javadoc。在该对象上使用以下方法

ExecutorService

的Javadoc:

  

创建并执行首先启用的定期操作   在给定的初始延迟之后,以及随后的给定时期;   那是执行将在initialDelay之后开始   initialDelay + period,然后是initialDelay + 2 * period,依此类推。

答案 1 :(得分:0)

您可以使用Thread.sleep()

    long time1 ,time2;
    while (true) {
        time1 = System.currentTimeMillis();
        yourMethod();
        time2 = System.currentTimeMillis();
        if((time2-time1) <200)
        Thread.sleep(200-(time2-time1)); 

    }

答案 2 :(得分:0)

你正在做一些图形化的东西,可能是为了Swing GUI。使用swing Timer而不是循环。这是最佳的。如果计算时间过长,请丢弃一帧:检查计时器回调是否正在进行计算,是否仍未进行事先计算。

实际上,如果您在计时器回调中显示先前计算的计算结果repaint / repaintImmediately,然后开始下一次计算,则帧速率将尽可能精确地保持。

也许使用双缓冲:

BufferedImage actualShown = new BufferedImage(...);

// Could be local to graphfunction:
BufferedImage beingCalculated = new BufferedImage(...);

@Override
public void repaintComponent(Graphics g) { // Called via repaint
    g.drawImage(actualShown, 0, 0);
}

void graphfunction(int increment) {
    // First draw old frame:
    repaint();

    // Calculations:
    ... beingCalculation.setRGB(x, y, Color.BLACK);

    // Double buffering:
    BufferedImage next = actualShown;
    actualShown = beingCalculated;
    beingCalculated = next;
}