英文:
how to run a code 60 times per second in java
问题
如果我不控制代码每秒执行的次数,当我添加一行代码时,程序的行为会变化,我必须再次调整常数。(由Google翻译)
我的代码失控运行:
public builder(){
while(true)
stepEvent();
}
private void stepEvent() {
setOfActions();
repaint();
}
英文:
if I don't control the number of times per second my code executes, when I add a line, the program varies and I have to adjust the constants again. (translated by Google)
My code running out of control:
public builder(){
while(true)
stepEvent();
}
private void stepEvent() {
setOfActions();
repaint();
}
答案1
得分: 2
import java.util.Timer;
import java.util.TimerTask;
public class HelloWorld {
public static void main(String []args) {
// 表示 1/60 秒中的毫秒数
// 这里可能会有一些四舍五入误差,
// 不确定这是否适用于您的用例
int ms = 1000 / 60;
Timer timer = new Timer();
timer.schedule(new SayHello(), 0, ms);
}
}
class SayHello extends TimerTask {
public void run() {
System.out.println("Hello World!");
}
}
英文:
import java.util.Timer;
import java.util.TimerTask;
public class HelloWorld {
public static void main(String []args) {
// number of ms in 1/60 of a second
// there will be some rounding error here,
// not sure if that's acceptable for your use case
int ms = 1000 / 60;
Timer timer = new Timer();
timer.schedule(new SayHello(), 0, ms);
}
}
class SayHello extends TimerTask {
public void run() {
System.out.println("Hello World!");
}
}
答案2
得分: 2
这只是一种方法(非常冗长但非常精确 - 我推荐用于游戏开发)。在这种情况下,我使用Runnable接口的run()
方法来执行代码。
public void run(){
long lastTime = System.nanoTime();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
while(true){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
// 要执行的代码
delta--;
}
}
}
逐行解释:
基本上,我在lastTime
中以纳秒存储当前时间。然后在ns
中,我以纳秒为单位存储了1/60秒的时间,并创建了变量delta
。
之后,我进入了一个无限的循环(不必无限),再次在now
中以纳秒为单位存储当前时间。这是为了考虑计算机从lastTime
声明行到循环行所花费的时间。
在做完所有这些之后,我将delta
增加了now
和lastTime
之差除以我提到的1/60秒(ns
)。这意味着每当delta
等于1时,将经过1/60秒。
紧接着,我让lastTime
与now
相同。在随后的while循环中,我检查delta是否等于或大于1,然后在其中,您应该放置您想要每秒执行60次的所有代码。不要忘记从delta
中减去1,这样它就不会无限循环。
仔细分析代码,看看是否能够理解。如果不能,我会进一步进行说明。我坚持认为这只是一种可能的方法,但还有许多其他方法。
注意:在某些情况下,您甚至可能根本不需要delta
,但它在某些情况下非常有用。
代码来源:大部分(至少我获取和学习的部分)来自TheCherno的游戏编程系列。
祝您度过愉快的一天!
英文:
This is just one way to do it(it's very long but VERY precise - I recommend it for game development). In this case I'm using the run()
method from the Runnable interface to execute the code.
public void run(){
long lastTime = System.nanoTime();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
while(true){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
the code you want to be executed
delta--;
}
}
}
Explanation Line by Line:
Basically, I store the current time in nanoseconds in lastTime
. Then in ns
I store 1/60th of a second in nanoseconds and create a variable delta
.
After this, I go inside the infinite while loop(it doesn't have to be infinite) and store the current time in nanoseconds once again in now
. This is to take into account the amount of time that took the computer to go from the lastTime
declaration line to the while loop line.
After doing all this, I add to delta
the difference of now
and lastTime
divided by the 1/60th of a second(ns
) I mentioned. This means that every time delta
is equal to 1, 1/60th of a second will have passed.
Right after this, I make lastTime
be the same as now
. In the while loop that comes afterwards I check if delta is equal or greater than 1 and then in there you should put all the code you want to be executed 60 times per second. Don't forget to substract 1 from delta
so it doesn't loop endlessly.
Analyze the code thoroughly and see if you can understand it. If you can't, I'll clarify further. I insist that this is just one possible way to do it, but there are many more ways.
Note: In some cases, you will never even need delta
, but it is very helpful for some purposes.
Credit for the code: Most of this code(at least where I got it & learned it) is extracted from TheCherno's Game Programming Series
Have a great day!
答案3
得分: -1
基本上,您需要每17毫秒执行一次stepEvent
。
在假设您想要顺序运行的情况下,您可以通过使用Thread.sleep(millis, nanos)
在一段定义的时间内停止执行。在这种情况下,我们将在线程执行时间为17毫秒减去stepEvent
执行时间(请考虑添加条件以避免在睡眠函数中出现负值)。
long startedTime;
for (;;) {
startedTime = System.currentTimeMillis();
stepEvent();
Thread.sleep(17 - (System.currentTimeMillis() - startedTime));
}
否则,您可以使用ScheduledExecutorService
,它允许您在固定的时间间隔(或在指定的延迟之后)定期安排代码运行。在这种情况下,您可以以固定的速率每17毫秒执行一次步骤。
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(YourClass::stepEvent, 0, 17, TimeUnit.MILLISECONDS);
您还可以配置使用Executors.newScheduledThreadPool
来使用多个线程。
英文:
Basically, you have to execute your stepEvent
every 17 ms.
With the assumption you want to run sequentially, you could stop the execution during a defined period by using Thread.sleep(millis , nanos)
. In this case, we will stop the thread 17ms minus the stepEvent
execution time (think to add condition to avoid negative value in sleep function)
long startedTime;
for(;;){
startedTime = System.currentTimeMillis();
stepEvent();
Thread.sleep(17 - System.currentTimeMillis() + startedTime);
}
Otherwise you can use the ScheduledExecutorService
which allows you to schedule code to run periodically at fixed time intervals (or after a specified delay). In this case, you can execute your step at a fixed rate every 17ms.
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(YourClass::stepEvent, 0, 17, TimeUnit.MILLISECONDS);
You can also configure to use severals thread with Executors.newScheduledThreadPool
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论