Java真正的固定时间间隔
Java real fixed time interval
我正在使用 Java 执行一些任务。我在计时方面遇到了一些问题:我需要设置一个具有固定重复周期的计时器。我尝试了标准 Timer
、TimerTask
和 ScheduledExecutor
,但两者都以近似的方式工作,即如果我设置 40 毫秒的间隔,使用以下代码(对于Executors
)
m_executor = Executors.newScheduledThreadPool(5);
Runnable thread = new TheThread();
m_executor.scheduleWithFixedDelay(thread, 0, 40000000, TimeUnit.NANOSECONDS);
然后我尝试打印每次执行的“时间”
private static final class TheThread implements Runnable {
@Override
public void run() {
System.out.println(System.nanoTime()/1000000);
}
}
结果是这样的:
xxxxxx300
xxxxxx345
xxxxxx386
xxxxxx428
...
如您所见,如果我正确理解 nanoTime()
该函数是随机调用的,接近我指定的时间间隔(40 毫秒),但不完全是我指定的!
例如,当我使用 C 和 Win32s 时,我能够使用高度准确的 CreateTimerQueueTimer()
函数,并且每 40 毫秒调用一次回调函数:
xxxxxx300
xxxxxx340
xxxxxx380
...
我试图移动时间测量以避免打印时间。我也尝试使用 scheduleAtFixedRate()
,但不幸的是周期在 35 到 47 毫秒之间变化(在方法中设置为 40)。
我想知道人们如何制作软件,例如模拟器或类似的东西,需要精确的周期遵守...:-)
我想到了一个可能的解决方案,我想向您展示并请教您,专家们:) 这个想法如何适用(和安全)
这里的问题是 运行 一些方法每 X 毫秒,比如 40 毫秒。这里的问题是关于 Java timer/timing,但是这个简单的解决方案呢?
public class MyEmulator extends Thread {
private long start = 0;
private long end = 0;
@Override
public void run() {
long exec_time;
start = System.nanoTime();
/*
* Do the emulator-loop
*/
end = System.nanoTime();
exe_time = (end - start)/1000000;
// wait with a whil() (40 - exec_time)
}
}
使用这个解决方案,当我在等待 whilt()
结束后打印经过的时间时,结果恰好是 40 毫秒(没有小数点,这并不重要)。
您认为这安全吗,即真的是 40 毫秒吗?
我认为您无法在 Java 中以这种精确度来管理它。与您的 C/Win32 解决方案不同,您的 Java 解决方案是 运行 在具有多个线程(不同优先级)和垃圾收集的 JVM 中 运行 宁并占用资源。
话虽如此,我将尝试使用定期执行的 scheduleAtFixedRate()
方法。 scheduleWithFixedDelay()
将执行并在完成后延迟一段固定的时间。因此,不考虑您的方法实际 运行 所花费的时间。
我正在使用 Java 执行一些任务。我在计时方面遇到了一些问题:我需要设置一个具有固定重复周期的计时器。我尝试了标准 Timer
、TimerTask
和 ScheduledExecutor
,但两者都以近似的方式工作,即如果我设置 40 毫秒的间隔,使用以下代码(对于Executors
)
m_executor = Executors.newScheduledThreadPool(5);
Runnable thread = new TheThread();
m_executor.scheduleWithFixedDelay(thread, 0, 40000000, TimeUnit.NANOSECONDS);
然后我尝试打印每次执行的“时间”
private static final class TheThread implements Runnable {
@Override
public void run() {
System.out.println(System.nanoTime()/1000000);
}
}
结果是这样的:
xxxxxx300
xxxxxx345
xxxxxx386
xxxxxx428
...
如您所见,如果我正确理解 nanoTime()
该函数是随机调用的,接近我指定的时间间隔(40 毫秒),但不完全是我指定的!
例如,当我使用 C 和 Win32s 时,我能够使用高度准确的 CreateTimerQueueTimer()
函数,并且每 40 毫秒调用一次回调函数:
xxxxxx300
xxxxxx340
xxxxxx380
...
我试图移动时间测量以避免打印时间。我也尝试使用 scheduleAtFixedRate()
,但不幸的是周期在 35 到 47 毫秒之间变化(在方法中设置为 40)。
我想知道人们如何制作软件,例如模拟器或类似的东西,需要精确的周期遵守...:-)
我想到了一个可能的解决方案,我想向您展示并请教您,专家们:) 这个想法如何适用(和安全)
这里的问题是 运行 一些方法每 X 毫秒,比如 40 毫秒。这里的问题是关于 Java timer/timing,但是这个简单的解决方案呢?
public class MyEmulator extends Thread {
private long start = 0;
private long end = 0;
@Override
public void run() {
long exec_time;
start = System.nanoTime();
/*
* Do the emulator-loop
*/
end = System.nanoTime();
exe_time = (end - start)/1000000;
// wait with a whil() (40 - exec_time)
}
}
使用这个解决方案,当我在等待 whilt()
结束后打印经过的时间时,结果恰好是 40 毫秒(没有小数点,这并不重要)。
您认为这安全吗,即真的是 40 毫秒吗?
我认为您无法在 Java 中以这种精确度来管理它。与您的 C/Win32 解决方案不同,您的 Java 解决方案是 运行 在具有多个线程(不同优先级)和垃圾收集的 JVM 中 运行 宁并占用资源。
话虽如此,我将尝试使用定期执行的 scheduleAtFixedRate()
方法。 scheduleWithFixedDelay()
将执行并在完成后延迟一段固定的时间。因此,不考虑您的方法实际 运行 所花费的时间。