【问题标题】:NTP Server without using System time不使用系统时间的 NTP 服务器
【发布时间】:2015-03-10 10:18:44
【问题描述】:

我有一台没有互联网连接或 GPS 接收器的台式电脑。我需要构建一个 NTP 服务器应用程序,最好是在 JAVA 中,而不使用系统时间。

我使用了以下方法。

public void run() 
    {
        Date oDate = new Date();
        time = oDate.getTime();

        System.out.println("Syst Time--->"+oDateFormat.format(time));
        while(true)
        {
            try 
            {
                Thread.sleep(100);
                time = time+100;
                oDate = new Date();
                if(time % 11443 == 1)
                {
                    System.out.println("Time--->"+oDateFormat.format(time)+" Syst Time--->"+oDateFormat.format(oDate));
                    oDate = null;
                }
            } 
            catch (InterruptedException ex) 
            {
                Logger.getLogger(NTPServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

我正在做的是有一个线程休眠 100 毫秒,然后我将 100 添加到 time 变量以保持我的时间。 但它每次打印时都会与系统时间产生 2-3 秒的差异。基本上是不准确的。

还有其他方法吗?

【问题讨论】:

  • 仅仅依靠 sleep() 永远不够准确。不能以系统时间为基准,将系统时间与GPS时间的差值存储为偏移量,在需要的时候计算出实时时间吗?当您每隔几秒或几分钟更新一次偏移量时,即使系统时间严重漂移,您也应该没问题。
  • 其实new Date()已经在使用系统时间了。
  • @SpaceTrucker 是的,我假设系统时间第一次是正确的,然后它会漂移。因此,我首先从系统中获取正确的时间,然后尝试防止它漂移。
  • @ThomasStets 但是那个偏移量是静态的,对吧?漂移是每小时一秒,非常大。所以说我最初得到 1 秒的偏移量,我不能在一天结束时减少太多的偏移量。
  • @Tattu 抱歉,看来我没有仔细阅读您的问题。我读到您 GPS 数据,而您实际上说没有。您的系统时间漂移是否恒定,即始终每小时一秒?然后,如果您知道多久以前第一次阅读,则可以弥补这一点。如果漂移本身发生波动,那你就不走运了。即使你设法从 sleep() 中获得了一些有意义的信息,这个方法本身也依赖于系统时钟。也许这可以帮助您调整时钟(如果您运行 Linux):linux.com/learn/docs/ldp/469-Clock

标签: java time ntp


【解决方案1】:

使用Thread.sleep(100); 并不能确保您的循环每 100 毫秒精确执行一次。至少有两点需要考虑:

  • 在调用 Thread.sleep(100) 之间执行的代码本身需要一些时间来执行。
  • Thread.sleep(100) 不睡准确 100ms,但它睡至少 100ms。当您的程序在 Thread.sleep() 未定义并取决于实现定义的方面(如 VM 调度程序和 OS 调度程序)之后真正继续时。

在具有不确定时序行为的环境中,软件无法测量时间。非确定性时序行为是由调度程序、缓存、多任务、多线程、硬盘等引起的。

您必须依赖系统时间,使用 System.currentTimeMillis()System.nanoTime()

【讨论】:

  • 是的,我知道 sleep(int),但我只是想评估漂移是如何进行的。它不会工作。这就是我发帖寻求帮助的原因:)
  • 我的目标是尽量减少时间漂移,比如一周内 1 秒左右。但我觉得你说得对,这似乎很难。
【解决方案2】:

您可以根据文档使用System.nanoTime()

此方法只能用于测量经过的时间,不能用于 与系统或挂钟时间的任何其他概念有关。

因此您在使用系统时间时不会违反您的要求。那么你基本上需要做到以下几点:

long before = System.nanoTime();
Thread.sleep(100);
long after = System.nanoTime();
time = time+((after-before)/1000000L);

您的生产代码应该注意 nanoTime 在睡眠期间可能发生的溢出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多