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

Java 如何使用System.nanoTime()更精确地对事件进行排序,java,time,Java,Time,每当应用程序中发生事件时,我希望附加一个时间戳。让我们假设一个客户端创建了一个事件对象,我想给该事件对象附加一个创建时间戳。我可以使用构造函数中的System.currentTimeMillis()来实现这一点。如果事件对象的创建速度不超过每毫秒一次,则此操作可以正常工作。在本例中,每个事件对象从System.currentTimeMillis()中获取不同的值,因此事件对象被排序 但是,如果事件对象的创建速度需要快于每毫秒一个对象,那么我的逻辑就中断了。根据对象创建的速率,2个或更多事件对象最

每当应用程序中发生事件时,我希望附加一个时间戳。让我们假设一个客户端创建了一个事件对象,我想给该事件对象附加一个创建时间戳。我可以使用构造函数中的System.currentTimeMillis()来实现这一点。如果事件对象的创建速度不超过每毫秒一次,则此操作可以正常工作。在本例中,每个事件对象从System.currentTimeMillis()中获取不同的值,因此事件对象被排序

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

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

我愿意将创建时间戳存储在事件类中,该事件类分为两个实例变量——creationTimeInMS(long)和creationTimeInNS(long)

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

我是否可以利用System.nanoTime提供事件对象的排序

注意-保证事件的创建速度不会超过每纳秒1次。因此,纳秒精度就足够了

我使用的代码如下所示

class Event {
private long timestamp

public Event() {
...
timestamp = System.currentTimeMillis()
}
因此,如果多个线程以每毫秒1次以上的速度调用事件构造函数,那么两个(或更多)事件对象将获得相同的时间戳


如果调用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;
    }
}
静态类单调时钟{
私人长袍;
公共时钟(){
last=System.currentTimeMillis();
}
公共同步长getNext(){
长电流=System.currentTimeMillis();
如果(上次<当前){//上次看到的值小于“现在”
last=当前值;
}否则{
last++;//碰撞,超频时间
}
最后返回;
}
}

在分布式系统中,事情更加复杂。您可能需要查看和了解这一点。

是否所有事件都在单个线程中处理/创建?如果是这样,一个简单的增量计数器(可能是ms时间戳之外的)就足够了。如果你真的对事件之间的精确时间感兴趣,这不会有帮助,但只关心它们的顺序。扩展@joachimsuer的答案:即使你使用多线程方法,你也可以使用
AtomicLong
作为计数器。至于您的问题:“我是否可以利用System.nanoTime来提供事件对象的排序?”我不理解这一点。如果保证事件的创建速度不超过每ns 1次,为什么时间戳(以ns为单位)不足以对对象进行排序?你能详细说明一下吗?@Turing85:没错,原子龙是一个很好的解决方案,即使是多线程的。nanoTime的问题在于它不能保证是单调递增的(特别是它会溢出)。因此,测量时间跨度(只要它们足够小)通常是好的,但不足以对带有时间戳的元素进行排序。@JoachimSauer,事件是从多个元素创建的threads@Turing85,在我的原始编辑中添加了一些注释