java - 如何使用 System.nanoTime() 更精确地对事件进行排序

标签 java time

每当我的应用程序中发生事件时,我想附加一个时间戳。假设客户端创建了一个 Event 对象,并且我想将创建时间戳附加到 Event 对象。我可以在构造函数中使用 System.currentTimeMillis() 来做到这一点。如果 Event 对象的创建速度不超过每毫秒一次,则此方法可以正常工作。在这种情况下,每个事件对象从 System.currentTimeMillis() 获得不同的值,因此事件对象被排序。

但是,如果需要以快于每毫秒创建一个对象的速率创建事件对象,那么我的逻辑就会中断。根据对象创建的速率,2 个或更多 Event 对象最终具有相同的创建时间戳(因为 System.currentTimeMillis 在快速连续调用时返回相同的值)

现在,在这种情况下,我该如何对事件对象进行排序?我知道 System.nanoTime() 但这与时代无关。

我愿意将创建时间戳存储在分为 2 个实例变量的 Event 类中 - creationTimeInMS(长)和 creationTimeInNS(长)

我不想使用支持纳秒精度的 java.sql.Timestamp

无论如何我可以利用 System.nanoTime 来提供事件对象的排序吗?

注意 - 保证事件的创建速度不会快于每纳秒 1 个。因此纳秒精度就足够了

我使用的代码如下

class Event {
private long timestamp

public Event() {
...
timestamp = System.currentTimeMillis()
}

因此,如果多个线程以快于每毫秒 1 次的速率调用 Event 构造函数,则两个(或更多)Event 对象将获得相同的时间戳。

如果调用速度不超过每纳秒一次,System.nanoTime() 应该返回唯一编号。但是我不确定如何将此数字与时间戳结合使用。我是否将其添加到时间戳以生成纳秒精度时间?

最佳答案

依靠挂钟很难实现,时间会发生冲突,并且在实践中很难实现纳秒分辨率,一个快速的解决方案是在时间周围添加一个包装器以记住其最后一个值。这当然不会在分布式环境中工作。

static class MonotonicClock{
    private long last;
    public MonotonicClock(){
        last = System.currentTimeMillis();
    }
    public synchronized long getNext(){
      long current = System.currentTimeMillis();
      if(last < current){ // last seen is less than "now"
        last = current;
      }else{
         last++; //collision, overclock the time
      }
      return last;
    }
}

在分布式系统中,事情要复杂得多。您可能需要查看 Lamport timestampsVector Clocks为此。

关于java - 如何使用 System.nanoTime() 更精确地对事件进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37208098/

相关文章:

java - 为什么书上说这里需要final?

java - 字符串的正则表达式验证

java - 您无权访问此服务器上的/schema/beans/spring-beans-3.1.xsd

swift - 从 "Start"时间计算 "End"时间

C# 没有用 .AddYears(1) 添加一年;

java - 使用整数 (1) 计算变量字符串 (010),其中结果为字符串 (011)

java - 对在客户端实现服务器负载共享的简单方法的看法

web-services - 通过 Web 服务调用进行时间同步

java - Android 比较纪元时间和今天日期并输出差异

python - 使用设定时间触发运动功能