繁体   English   中英

如何在1秒内执行n次循环

[英]how to execute a loop n times in 1 second

我试图在一秒钟内执行N次指令或函数N次。 我怎么能在java中这样做? 如下...

//in one second
while(N)
{
  printf(".........");
  int x=0;
  printf("The value of x is ");
}

但问题实际上变得更深了..我试图手动绘制像素,我想要每秒旋转效果没有...所以基本上,它必须执行N次一秒钟(但这是无限制的)

提前致谢

你永远无法确定它每秒会发生N次,但它是这样的:

long taskTime = 0;
long sleepTime = 1000/N;
while (true) {
  taskTime = System.currentTimeMillis();
  //do something
  taskTime = System.currentTimeMillis()-taskTime;
  if (sleepTime-taskTime > 0 ) {
    Thread.sleep(sleepTime-taskTime);
  }
}

我会翻转这个问题:不要在一秒钟内将循环限制为N次。 相反,处理N个工作单元在所需时间内均匀分布。

也就是说,计算自开始 (或之前的工作 )以来经过了多长时间,将其插入到工作率中 ,并做了那么多工作 (开始/上一次的因素和已经完成的工作量)。 这是许多游戏/动画引擎的基本支撑 - 一个“增量时间”

然后在每个循环结束时调用yield以“很好” - 或者更确切地说,防止吃掉99%以上的CPU使用量! 屈服本身具有最小分辨率1 ,但效果通常是足够的,特别是在适当插值时。

因为使用了插值方法,所以这应该适用于所有N( 可以在分配的时间内运行),即使这意味着每个循环执行更多N. 这也有可能是没有工作可以做任何特别的循环了小的N,但yield ,使这种“异常忙碌循环” CPU利用率2方面便宜。


这里有一些伪代码可以在一秒内打印出20“x”s, now返回小数秒:

rate = 20       // per second - "N times per second"
done = 0
goal = 1 * rate // same as rate for 1 second
start = now()
while done < goal:
    target = floor((now() - start) * rate)
    work = (target - done) // work might be 0, that's okay
    for 0 upto work:
         print("x")
    done += work
    yield()

在这种情况下,由于恒定速率公式,很容易插入开始时间。 使用基于自上次工作(或循环)以来的时间的“增量时间”是相似的并且在没有离散公式时是合适的,但是稍微更复杂并且可能导致细微的漂移误差。


1 实际 sleep/yield的时间分辨率取决于实施方式,因系统而异。 例如,它可能从Linux上的1毫秒到Windows上的10-15毫秒

2根据Dariusz Wawer的回答, 除了处理时间增量外, sleep周期也可以改变。 然而,这增加了复杂性并且简单的yield通常就足够了。

很难与所提出的解决方案相配合。 而不是计算迭代之间的差距,计算下一次迭代应该执行的绝对时间。 这更准确,因为迭代不依赖于先前的迭代。

long startTime = System.currentTimeMillis();
long msPerIteration = 1000000/iterationsPerSecond;
long i=0;
while (true) {
    // do stuff

    long msWaiting = startTime + (msPerIteration * ++i) - System.currentTimeMillis();

    if (msWaiting > 0)
        Thread.sleep(msWaiting);
}

我今天不得不写一个游戏循环。 我使用了一个溢出变量,确保如果之前的那个太快,下一个tick会等待更长时间。 每个tick都会删除一半溢出并使用它来影响帧时间。

new Thread() {
        public void run() {
            long overflow = 0; // The greater the overflow, the slower the game had calculated the last tick, and the shorter this tick's wait needs to be
            long lastStartTime = System.nanoTime();
            while(true) {
                long startTime = System.nanoTime();
                overflow += (startTime - lastStartTime) - 16666667; // 16.67 milliseconds = 60 fps

                tick();

                long endTime = System.nanoTime();
                long waitTime = 16666667 - (endTime - startTime) - overflow / 2;
                try {
                    Thread.sleep(waitTime / 1000000, (int) (waitTime % 1000000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                overflow /= 2; // Do not remove all overflow at once to prevent oscillation of ticktime
                lastStartTime = startTime;
            }
        }
    }.start();

将循环更改为while(true)

检查while循环之前的时间(以毫秒为单位)。 while循环结束时,以毫秒为单位获取时间,看看是否已经传递了1000个时间。 如果这样break

伪代码:

Create Timer t;
t.Start;
int counter = N;
While ((t.Elapsedtime < 1 Second) AND (N > 0))
{
    call your_function();
    N--;
}

your_function()
{
    printf(".........");
    int x=0;
    printf("The value of x is ");
}
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start <= 1000) {
  // Your code goes here
}

需要注意的是,您的代码将循环1000毫秒。 它完成的次数是不确定的,并且每次运行可能会有所不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM