我有一个课程,从过去的时间起充当时钟,可以以不同的速度播放。在下面的示例代码中,我正在以60x播放。
我注意到时间每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
答案 0 :(得分:1)
只需将时间基于您知道准确的来源......对于临时应用,系统时钟通常足够好。如果您尝试让您的应用帐户占用时间,那么您的精度将受到JVM的并发稳健性的限制。而且,老实说,这不是JVM打算做得好的事情。
答案 1 :(得分:1)
由于您的流程正在处理其他操作已经过了一段时间,因此您有时间漂移。而不是Thread.sleep(int)
,请尝试java.util.Timer.scheduleAtFixedRate(task, date, period)
。 Timer内部计算下一个执行时间并在指定时间触发。这个触发也是由Timer使用wait-notify锁定机制在内部完成的。简而言之,您必须实现更新时钟的TimerTask,然后使用Timer以所需的时间间隔(例如1000ms)安排任务。
答案 2 :(得分:0)
为什么不直接使用系统时钟?
initialStartTime = System.currentTimeMillis();
while (true){
if (intialStartTime - System.currentTimeMillis() % 1000 == 0){
System.out.println(calendar.getTime());
}
}
显然,你需要在后台线程上运行上面的代码,而不是while(true)有一些合理的退出条件。 SO上有关于线程等的大量信息。