2013-05-17 2 views
1

나는 과거와 다른 시간에 재생할 수있는 클럭으로 작동하는 클래스가 있습니다. 아래의 예제 코드에서는 60x에서 재생 중입니다.자바 : 시간 드리프트

나는 10 초마다 시간이 흐르지 만 나는 그것에 대처하는 방법을 알고있다. 당신이 "초"에서 볼 수 있듯이

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 

이 감도는 : 여기

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: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 
+5

글쎄,이 문제는 충분히 간단합니다. Thread.sleep은 정확한 함수가 아니며 많은 (많은) 반복을 처리하는 처리 시간도 고려하지 않습니다. 하지만 어떻게 해결해야할지 모르겠다. – Alex

답변

0

왜 시스템 시계를 직접 사용하지 않습니까?

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

분명히 위의 내용은 백그라운드 스레드에서 실행하고 while (true) 대신에 적당한 종료 조건이 있어야합니다. SO에 대한 스레드 등에 관한 많은 정보가 있습니다.

1

정확하게 알고있는 소스를 기반으로 시간을 정하십시오. 캐주얼 응용 프로그램의 경우 일반적으로 시스템 클럭으로 충분합니다. 앱 계정을 사용하려고하면 JVM의 동시성 견고성으로 인해 정밀도가 제한 될 것입니다. 솔직히 말해서 이것은 JVM이 잘하도록 의도 된 종류가 아닙니다.

+0

실제로 Java는 중요한 타이밍 응용 프로그램이 아닌 일반적인 비즈니스 응용 프로그램 용으로 개발되었습니다. 그러나 특수한 [실시간 Java] (http://en.m.wikipedia.org/wiki/Real_time_Java) 구현을 시도하고 있습니다. –

1

프로세스가 다른 작업을 수행 중일 때 약간의 시간이 경과 했으므로 시간 편차가 있습니다. Thread.sleep(int) 대신 java.util.Timer.scheduleAtFixedRate(task, date, period)을 시도하십시오. 타이머는 내부적으로 다음 실행 시간을 계산하고 지정된 시간에 트리거합니다. 이 트리거는 대기 알림 잠금 메커니즘을 사용하여 Timer에 의해 내부적으로 수행됩니다. 즉, 시계를 업데이트하는 TimerTask를 구현 한 다음 타이머를 사용하여 원하는 간격 (예 : 1000ms)으로 작업을 예약해야합니다.

+0

이것은 실제로 ms에서 매 1000ms마다 실행되도록 보장됩니까? 아니면 그 구장에서 뭔가를 얻을 수 있을까요? – Alex

+0

보장이 없기 때문에 타이머가 "오작동"할 수 있습니다 (트리거 타이밍을 놓치십시오). 이것은 일반적으로 큰 번호가있는 환경에서 발생합니다. 스레드 풀의 수가 적습니다. 일반적인 경우에는 타이밍이 매우 정확합니다. – happymeal