java 如何在 1 秒内执行 n 次循环
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14746072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to execute a loop n times in 1 second
提问by JS_VIPER
I am trying to execute couple of instructions or a function N times in one second. How can i do this in java? As follows...
我试图在一秒钟内执行几条指令或一个函数 N 次。我怎么能在java中做到这一点?如下...
//in one second
while(N)
{
printf(".........");
int x=0;
printf("The value of x is ");
}
but the question actually goes little deeper.. I am trying to plot pixels manually and I want the no of rotations per second effect... so basically, it has to execute N times for a second (But this is done infinitely )
但这个问题实际上更深入一些..我正在尝试手动绘制像素,我想要每秒旋转数的效果......所以基本上,它必须在一秒钟内执行 N 次(但这是无限执行的)
thanks in advance
提前致谢
回答by Dariusz
You can never be sure it will happen exactly N times per second, but it goes like this:
你永远无法确定它每秒会发生 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);
}
}
回答by Dariusz
I would flip the issue: don't limit the loop to N times in a second. Instead, process N units of work evenly distributed over the desired time.
我想解决这个问题:不要在一秒钟内将循环限制为 N 次。相反,处理 N 个工作单元,在所需的时间内均匀分布。
That is, compute how much time has passed since the start(or previous work), interpolate that into the rate of work, and do that much work(factor in the start/previous time and the amount of work that has been done). This is the fundamental underpinning of many game/animation engines - a "delta time".
也就是说,计算自开始(或之前的工作)以来已经过去了多少时间,将其插入到工作率中,然后做那么多工作(考虑开始/上一次的时间和已经完成的工作量)。这是许多游戏/动画引擎的基础—— “增量时间”。
Then call yield
at the end of each loop to "be nice" - or rather, to prevent eating 99%+ CPU usage! The yield itself has a minimum resolution1, but the effects are generally adequate, especially when interpolating suitably.
然后yield
在每个循环结束时调用以“保持良好” - 或者更确切地说,防止占用 99% 以上的 CPU 使用率!产量本身具有最小分辨率1,但效果通常是足够的,尤其是在适当插值时。
Because an interpolation approach is used, this should work for all N (that canrun in the allotted time), even if it means doing many more N each loop. It is also possible that no work might be done any particular loop for a small N but the yield
makes this sort of "extra busy looping" cheap in terms of CPU utilization2.
因为使用了插值方法,这应该适用于所有 N(可以在分配的时间内运行),即使这意味着每个循环执行更多 N。也有可能对于一个小的 N 没有任何特定的循环完成任何工作,但这yield
使得这种“额外繁忙的循环”在 CPU 利用率方面变得便宜2。
Here is some pseudo-code to print out 20 "x"s in a second, where now
returns fractional seconds:
这是一些伪代码,可以在一秒钟内打印出 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()
In this case it is easy to interpolate off of the start time because of the constant rate formula. Using a "delta time" based off the time since the last work (or loop) is similar and is suitable when there is no discrete formula, but is slightly more complex and can lead to subtle drift errors.
在这种情况下,由于采用恒定速率公式,很容易在开始时间之外进行插值。使用基于自上次工作(或循环)以来的时间的“增量时间”是类似的,适用于没有离散公式的情况,但稍微复杂一些,并可能导致细微的漂移错误。
1The time resolution of an actualsleep/yield
is implementation-dependent and varies by by system. For instance, it might range from as low as 1ms on Linux to 10-15ms on windows.
1实际的时间分辨率sleep/yield
取决于实现,并因系统而异。例如,它的范围可能从Linux 上的 1ms 到 Windows 上的 10-15ms。
2In addition todealing with a time delta, the sleep
period can be altered, as per Dariusz Wawer's answer. However, this adds complexity and a simple yield
is often sufficient.
2在除了处理一个时间差,该sleep
时间段可以改变,按了Dariusz Wawer的答案。然而,这增加了复杂性,简单yield
的通常就足够了。
回答by Daniel Argüelles
It is difficult to be acurate with the proposed solutions. Instead of calculate the gap between iterations, calculate the absolute time when the next iteration should be executed. This is more accurate because iterations don't depend on previous ones.
很难准确地使用所提出的解决方案。不是计算迭代之间的间隔,而是计算应该执行下一次迭代的绝对时间。这更准确,因为迭代不依赖于以前的迭代。
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);
}
回答by user10827677
I had to write a game loop today. I used an overflow variable that makes sure that the next tick will wait longer if the previous ones were too quick. Every tick removes half of the overflow and uses it to influence the frametime.
我今天必须写一个游戏循环。我使用了一个溢出变量,以确保如果前一个滴答太快,下一个滴答将等待更长时间。每个滴答都会消除一半的溢出并使用它来影响帧时间。
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();
回答by Krystian Cybulski
Change the loop to while(true)
.
将循环更改为while(true)
。
Check the time in milliseconds before your while
loop. At the end of the while
loop get the time in milliseconds and see if 1000 of them have passed. If so break
.
在while
循环之前检查时间(以毫秒为单位)。在while
循环结束时获取以毫秒为单位的时间,并查看其中的 1000 个是否已经过去。如果是这样break
。
回答by CloudyMarble
Pseudo Code:
伪代码:
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 ");
}
回答by hthserhs
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start <= 1000) {
// Your code goes here
}
All it takes care is that your code will be looped over for 1000 milliseconds. The number of times it's done is uncertain and may vary on each run.
需要注意的是,您的代码将循环 1000 毫秒。完成的次数是不确定的,每次运行可能会有所不同。