使用持续时间为 1 毫秒且循环计数不确定的时间轴是否可以为秒表提供准确的时间?
Will using a Timeline with a duration of 1 millisecond with an indefinite cycle count provide an accurate time for a stopwatch?
我使用时间轴创建了一个简单的秒表,但我想知道它是否准确。这是代码:
LongProperty timeMillis = new SimpleLongProperty(0);
timer = new Timeline(new KeyFrame(Duration.millis(1), e -> timeMillis.set(timeMillis.get()+1));
timer.setCycleCount(Timeline.INDEFINITE);
timer.start();
我的问题是,在增加 timeMillis 的同时,每毫秒之间是否会有某种延迟?还是一次计数1毫秒导致的某种延迟?
根据 Jon Skeet 的建议,我自己计时,似乎还算准。
LongProperty timelineMillis = new SimpleLongProperty(0);
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(1), e -> timelineMillis.set(timelineMillis.get()+1)));
timeline.setCycleCount(Timeline.INDEFINITE);
Long startNano = System.nanoTime();
timeline.play();
Timeline checkTime = new Timeline(new KeyFrame(Duration.millis(1000), e -> {
Long currentTimelineTime = timelineMillis.get();
Long currentNanoTime = (System.nanoTime() - startNano) / 1000000;
System.out.println("Timeline time: " + currentTimelineTime + ", Nano time: " + currentNanoTime + ", Difference: " + (currentTimelineTime - currentNanoTime));
}));
checkTime.setCycleCount(Timeline.INDEFINITE);
checkTime.play();
前 30 秒的输出:
Timeline time: 1010, Nano time: 1012, Difference: -2
Timeline time: 2002, Nano time: 2004, Difference: -2
Timeline time: 3010, Nano time: 3012, Difference: -2
Timeline time: 4002, Nano time: 4004, Difference: -2
Timeline time: 5010, Nano time: 5012, Difference: -2
Timeline time: 6002, Nano time: 6004, Difference: -2
Timeline time: 7010, Nano time: 7012, Difference: -2
Timeline time: 8002, Nano time: 8004, Difference: -2
Timeline time: 9010, Nano time: 9012, Difference: -2
Timeline time: 10002, Nano time: 10004, Difference: -2
Timeline time: 11010, Nano time: 11012, Difference: -2
Timeline time: 12002, Nano time: 12004, Difference: -2
Timeline time: 13010, Nano time: 13012, Difference: -2
Timeline time: 14003, Nano time: 14004, Difference: -1
Timeline time: 15011, Nano time: 15012, Difference: -1
Timeline time: 16003, Nano time: 16004, Difference: -1
Timeline time: 17011, Nano time: 17012, Difference: -1
Timeline time: 18002, Nano time: 18003, Difference: -1
Timeline time: 19010, Nano time: 19011, Difference: -1
Timeline time: 20002, Nano time: 20004, Difference: -2
Timeline time: 21010, Nano time: 21012, Difference: -2
Timeline time: 22002, Nano time: 22004, Difference: -2
Timeline time: 23010, Nano time: 23012, Difference: -2
Timeline time: 24002, Nano time: 24004, Difference: -2
Timeline time: 25010, Nano time: 25012, Difference: -2
Timeline time: 26002, Nano time: 26004, Difference: -2
Timeline time: 27010, Nano time: 27012, Difference: -2
Timeline time: 28002, Nano time: 28004, Difference: -2
Timeline time: 29010, Nano time: 29012, Difference: -2
Timeline time: 30002, Nano time: 30004, Difference: -2
您的时间轴方法相当准确,但计算时间的频率远高于 UI 能够呈现的时间。默认情况下,JavaFX 以每秒 60 帧的速度限制帧渲染,因此只有大约 6% 的 timemillis.set(...)
调用会在 UI.
中表示
一种更有效的方法是使用 AnimationTimer
,它在呈现 UI 时执行计算,但不会更频繁地执行计算。 AnimationTimer
有一个 handle()
方法,保证每个渲染脉冲只执行一次:
LongProperty timeMillis = new SimpleLongProperty(0);
AnimationTimer stopwatch = new AnimationTimer() {
private static final long STOPPED = -1 ;
private long startTime = STOPPED ;
@Override
public void handle(long timestamp) {
if (startTime == STOPPED) {
startTime = timestamp ;
}
long elapsedNanos = timestamp - startTime ;
long elapsedMillis = elapsedNanos / 1_000_000 ;
timeMillis.set(elapsedMillis);
}
@Override
public void stop() {
startTime = STOPPED ;
super.stop();
}
};
现在只需调用 stopwatch.start()
和 stopwatch.stop()
即可启动和停止计时器。您也可以添加一些 pause()
功能,这需要更多的工作...
我使用时间轴创建了一个简单的秒表,但我想知道它是否准确。这是代码:
LongProperty timeMillis = new SimpleLongProperty(0);
timer = new Timeline(new KeyFrame(Duration.millis(1), e -> timeMillis.set(timeMillis.get()+1));
timer.setCycleCount(Timeline.INDEFINITE);
timer.start();
我的问题是,在增加 timeMillis 的同时,每毫秒之间是否会有某种延迟?还是一次计数1毫秒导致的某种延迟?
根据 Jon Skeet 的建议,我自己计时,似乎还算准。
LongProperty timelineMillis = new SimpleLongProperty(0);
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(1), e -> timelineMillis.set(timelineMillis.get()+1)));
timeline.setCycleCount(Timeline.INDEFINITE);
Long startNano = System.nanoTime();
timeline.play();
Timeline checkTime = new Timeline(new KeyFrame(Duration.millis(1000), e -> {
Long currentTimelineTime = timelineMillis.get();
Long currentNanoTime = (System.nanoTime() - startNano) / 1000000;
System.out.println("Timeline time: " + currentTimelineTime + ", Nano time: " + currentNanoTime + ", Difference: " + (currentTimelineTime - currentNanoTime));
}));
checkTime.setCycleCount(Timeline.INDEFINITE);
checkTime.play();
前 30 秒的输出:
Timeline time: 1010, Nano time: 1012, Difference: -2
Timeline time: 2002, Nano time: 2004, Difference: -2
Timeline time: 3010, Nano time: 3012, Difference: -2
Timeline time: 4002, Nano time: 4004, Difference: -2
Timeline time: 5010, Nano time: 5012, Difference: -2
Timeline time: 6002, Nano time: 6004, Difference: -2
Timeline time: 7010, Nano time: 7012, Difference: -2
Timeline time: 8002, Nano time: 8004, Difference: -2
Timeline time: 9010, Nano time: 9012, Difference: -2
Timeline time: 10002, Nano time: 10004, Difference: -2
Timeline time: 11010, Nano time: 11012, Difference: -2
Timeline time: 12002, Nano time: 12004, Difference: -2
Timeline time: 13010, Nano time: 13012, Difference: -2
Timeline time: 14003, Nano time: 14004, Difference: -1
Timeline time: 15011, Nano time: 15012, Difference: -1
Timeline time: 16003, Nano time: 16004, Difference: -1
Timeline time: 17011, Nano time: 17012, Difference: -1
Timeline time: 18002, Nano time: 18003, Difference: -1
Timeline time: 19010, Nano time: 19011, Difference: -1
Timeline time: 20002, Nano time: 20004, Difference: -2
Timeline time: 21010, Nano time: 21012, Difference: -2
Timeline time: 22002, Nano time: 22004, Difference: -2
Timeline time: 23010, Nano time: 23012, Difference: -2
Timeline time: 24002, Nano time: 24004, Difference: -2
Timeline time: 25010, Nano time: 25012, Difference: -2
Timeline time: 26002, Nano time: 26004, Difference: -2
Timeline time: 27010, Nano time: 27012, Difference: -2
Timeline time: 28002, Nano time: 28004, Difference: -2
Timeline time: 29010, Nano time: 29012, Difference: -2
Timeline time: 30002, Nano time: 30004, Difference: -2
您的时间轴方法相当准确,但计算时间的频率远高于 UI 能够呈现的时间。默认情况下,JavaFX 以每秒 60 帧的速度限制帧渲染,因此只有大约 6% 的 timemillis.set(...)
调用会在 UI.
一种更有效的方法是使用 AnimationTimer
,它在呈现 UI 时执行计算,但不会更频繁地执行计算。 AnimationTimer
有一个 handle()
方法,保证每个渲染脉冲只执行一次:
LongProperty timeMillis = new SimpleLongProperty(0);
AnimationTimer stopwatch = new AnimationTimer() {
private static final long STOPPED = -1 ;
private long startTime = STOPPED ;
@Override
public void handle(long timestamp) {
if (startTime == STOPPED) {
startTime = timestamp ;
}
long elapsedNanos = timestamp - startTime ;
long elapsedMillis = elapsedNanos / 1_000_000 ;
timeMillis.set(elapsedMillis);
}
@Override
public void stop() {
startTime = STOPPED ;
super.stop();
}
};
现在只需调用 stopwatch.start()
和 stopwatch.stop()
即可启动和停止计时器。您也可以添加一些 pause()
功能,这需要更多的工作...