9

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

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

但问题实际上更深一些..我正在尝试手动绘制像素,我想要每秒旋转次数的效果......所以基本上,它必须在一秒钟内执行 N 次(但这是无限次完成的)

提前致谢

4

7 回答 7

6

你永远不能确定它每秒会发生 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);
  }
}
于 2013-02-07T07:45:12.423 回答
5

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

也就是说,计算自开始(或之前的工作)以来已经过去了多少时间,将其插入到工作速率中,然后做那么多的工作(考虑开始/之前的时间和已经完成的工作量)。这是许多游戏/动画引擎的基本基础—— “增量时间”

然后yield在每个循环结束时调用“be nice”——或者更确切地说,防止消耗 99%+ 的 CPU 使用率!产量本身具有最小分辨率1,但效果通常是足够的,尤其是在适当插值时。

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


下面是一些伪代码,可以在一秒钟内打印出 20 个“x”,其中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 上的 1ms 到 windows 上的 10-15ms不等。

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

于 2013-02-07T07:54:21.057 回答
1

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

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);
}
于 2018-01-15T11:59:30.907 回答
1

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

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();
于 2018-12-24T03:22:45.073 回答
0

将循环更改为while(true).

while在循环之前检查时间(以毫秒为单位) 。在while循环结束时获取以毫秒为单位的时间,并查看其中是否有 1000 个已经过去。如果是这样break

于 2013-02-07T07:45:57.163 回答
0

伪代码:

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 ");
}
于 2013-02-07T07:48:19.503 回答
0
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start <= 1000) {
  // Your code goes here
}

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

于 2013-02-07T07:49:20.203 回答