1

我有一个类可以作为过去某个时间的时钟,可以以不同的速度播放。在下面的示例代码中,我以 60 倍的速度播放。

我注意到时间每 10 秒漂移一秒左右,我想知道如何处理它。

import java.util.Calendar;

public class Clock {

    long delta;
    long lastCalledTime;
    long startingTime;
    private float speed = 1f;

    public synchronized long getAdjustedTimeMillis() {
        long time = (System.currentTimeMillis() - (delta));
        long val = (startingTime + (long) ((time - lastCalledTime) * speed));
        return val;
    }

    public synchronized void setPlaybackSpeedFromTime(float speed, long startingTime) {
        this.startingTime = startingTime;
        this.delta = System.currentTimeMillis() - startingTime;
        this.speed = speed;
        this.lastCalledTime = System.currentTimeMillis() - delta;
    }

    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(2010, 4, 4, 4, 4, 4);
        Clock clock = new Clock();
        clock.setPlaybackSpeedFromTime(60f, calendar.getTimeInMillis());
        for (int i = 0; i < 1000; i++) {
            calendar.setTimeInMillis(clock.getAdjustedTimeMillis());
            System.out.println(calendar.getTime());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }


    }

}

这是我得到的输出:

Tue May 04 04:04:04 PDT 2010
Tue May 04 04:05:06 PDT 2010
Tue May 04 04:06:06 PDT 2010
Tue May 04 04:07:06 PDT 2010
Tue May 04 04:08:06 PDT 2010
Tue May 04 04:09:06 PDT 2010
Tue May 04 04:10:06 PDT 2010
Tue May 04 04:11:06 PDT 2010
Tue May 04 04:12:06 PDT 2010
Tue May 04 04:13:07 PDT 2010
Tue May 04 04:14:07 PDT 2010
Tue May 04 04:15:07 PDT 2010
Tue May 04 04:16:07 PDT 2010
Tue May 04 04:17:07 PDT 2010
Tue May 04 04:18:07 PDT 2010
Tue May 04 04:19:07 PDT 2010
Tue May 04 04:20:07 PDT 2010
Tue May 04 04:21:07 PDT 2010
Tue May 04 04:22:07 PDT 2010
Tue May 04 04:23:08 PDT 2010
Tue May 04 04:24:08 PDT 2010

如您所见,“秒”漂移。我想要的是这样的:

Tue May 04 04:04:04 PDT 2010
Tue May 04 04:05:04 PDT 2010
Tue May 04 04:06:04 PDT 2010
Tue May 04 04:07:04 PDT 2010
Tue May 04 04:08:04 PDT 2010
Tue May 04 04:09:04 PDT 2010
Tue May 04 04:10:04 PDT 2010
Tue May 04 04:11:04 PDT 2010
Tue May 04 04:12:04 PDT 2010
Tue May 04 04:13:04 PDT 2010
Tue May 04 04:14:04 PDT 2010
Tue May 04 04:15:04 PDT 2010
Tue May 04 04:16:04 PDT 2010
Tue May 04 04:17:04 PDT 2010
Tue May 04 04:18:04 PDT 2010
Tue May 04 04:19:04 PDT 2010
Tue May 04 04:20:04 PDT 2010
Tue May 04 04:21:04 PDT 2010
Tue May 04 04:22:04 PDT 2010
Tue May 04 04:23:04 PDT 2010
Tue May 04 04:24:04 PDT 2010
4

3 回答 3

1

您有时间漂移,因为当您的流程进行其他操作时已经过了一段时间。而不是Thread.sleep(int),尝试java.util.Timer.scheduleAtFixedRate(task, date, period)。Timer 内部计算下一次执行时间并在指定时间触发。此触发也由 Timer 使用等待通知锁定机制在内部完成。简而言之,您必须实现 TimerTask 来更新您的时钟,然后使用 Timer 以所需的时间间隔(例如 1000 毫秒)安排任务。

于 2013-05-17T01:54:32.557 回答
1

只需将您的时间基于您知道将是准确的来源......对于临时应用程序,系统时钟通常足够好。如果您尝试让您的应用程序考虑时间,那么您的精度将受到 JVM 并发鲁棒性的限制。而且,老实说,这不是 JVM 打算做好的事情。

于 2013-05-17T01:39:13.433 回答
0

为什么不直接使用系统时钟?

initialStartTime = System.currentTimeMillis();
while (true){
    if (intialStartTime - System.currentTimeMillis() % 1000 == 0){
        System.out.println(calendar.getTime());
    }
}

显然,您需要在后台线程上运行上述程序,而不是 while(true) 有一些合理的退出条件。SO上有很多关于线程等的信息。

于 2013-05-17T01:30:01.520 回答