2016-05-13 57 views
2

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

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

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

我打开存储事件类组内的创建时间戳到2个实例变量 - creationTimeInMS(长)和creationTimeInNS(长)

我不想的java.sql.Timestamp它不支持纳米第二精度

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

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

的代码,我使用是如下

class Event { 
private long timestamp 

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

因此,如果在事件的构造方法由多个线程的速率称为比1每毫秒快,然后两个(或更多)事件对象获得相同的时间戳。

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

+1

所有事件是在单个线程中处理/创建的吗?如果是这样,一个简单的增量计数器(可能除了ms时间戳)就足够了。如果您真的对事件之间的确切时间感兴趣,但只关心他们的订购,这将无济于事。 –

+0

扩展@JoachimSauer的答案:即使您使用多线程方法,您也可以使用AtomicLong作为计数器。至于你的问题:“无论如何,我可以利用System.nanoTime来提供事件对象的排序?”这我不明白。如果确保事件的创建速度不超过每ns 1个,为什么时间戳(以ns为单位)不足以排序对象?你能详细说明一下吗? – Turing85

+0

@ Turing85:的确,即使多线程,AtomicLong也是一个非常好的解决方案。nanoTime的问题在于不能保证单调递增(具体而言,它可以并且会溢出)。所以通常测量时间跨度是很好的(只要它们足够小),但不足以对具有时间戳的元素进行排序。 –

回答

1

依靠挂钟很难实现这一点,时间会发生碰撞,而纳秒级分辨率在实践中很难实现,快速解决方案是在记忆最后一个值的时候添加一个包装。当然,这个不会在分布式环境中工作。

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