在Java中创建唯一的时间戳

问题描述:

我需要在Java中创建一个保证在该特定VM实例中唯一的时间戳(以毫秒为单位)。即需要一些方法来限制System.currentTimeMillis()的吞吐量,以便每ms返回一个结果。任何想法如何实现?在Java中创建唯一的时间戳

+2

我不知道你是什么意思*节流*的currentTimeMillis(),使其返回*最多*一个结果EV唔好?如果你想要独特的时间戳,你更愿意保证它在每次调用时都返回一个不同的值,对吧? – 2012-02-08 10:16:19

+0

他们必须单调增加吗?他们是否必须与实际*时间*有任何关系?他们必须在多次运行中保持独特吗? – 2012-02-08 10:17:29

这会使时间尽可能地接近当前时间而没有重复。

private static final AtomicLong LAST_TIME_MS = new AtomicLong(); 
public static long uniqueCurrentTimeMS() { 
    long now = System.currentTimeMillis(); 
    while(true) { 
     long lastTime = LAST_TIME_MS.get(); 
     if (lastTime >= now) 
      now = lastTime+1; 
     if (LAST_TIME_MS.compareAndSet(lastTime, now)) 
      return now; 
    } 
} 

避免每毫秒限制一个ID的一种方法是使用微秒时间戳。即将currentTimeMS乘以1000.这将允许每毫秒1000个ID。注意:如果时间倒退(例如,由于NTP校正),则每次调用时间将以1毫秒为单位进行,直到时间赶上为止。 ;)

+0

谢谢!正是我需要的! – Yrlec 2012-02-08 10:29:26

+0

正确使用,即使重新启动应用程序后,这也意味着您将拥有唯一的ID。 – 2012-02-08 10:32:18

+1

听起来不错! “正确使用”的意思是什么? – Yrlec 2012-02-08 10:44:11

您可以使用System.nanoTime(),这是最精确的可用系统计时器,并将其除以百万以获得毫秒。尽管对更新频率没有正式的保证,但我认为可以合理地假定它每隔毫秒更新一次(数量级更高)。当然,如果您创建的时间间隔小于毫秒,那么它们不能全部是唯一的。

请注意,绝对值nanoTime()是任意的。如果您想要绝对时间,请以某种方式进行校准,即在启动时将其与currentTimeMillis()进行比较。

可以使用System.nanoTime()具有更高的精度

虽然我尝试以下,每次它赋予不同的值,它可能不能保证是唯一的所有的时间。

public static void main(String[] args) { 
     long time1 = System.nanoTime(); 
     long time2 = System.nanoTime(); 
     long time3 = System.nanoTime(); 
     System.out.println(time1); 
     System.out.println(time2); 
     System.out.println(time3); 
    } 

另一种方法是使用AtomicInteger/AtomicLong类唯一的数字,如果时间不是对你很重要,你只需要唯一的号码,这可能是一个btter选择。

+2

nanoTime是单调的,但并不总是唯一的。你可以得到很多重复。例如在Red Hat&Centos 5.x上,分辨率是微秒级的,所以你会得到很多重复的值。 – 2012-02-08 10:33:33

+0

感谢您的信息。我猜想它取决于操作系统和机器。 – fmucar 2012-02-08 11:40:53

+1

您可以使用nanoTime进行与其不同的检查。 (与我的解决方案类似)nanoTime是许多系统上的正常运行时间。 – 2012-02-08 12:01:45

请问您是否可以使用java.util.UUID和它的timestamp()clockSequence()

Method Summary 
    int clockSequence() 
     The clock sequence value associated with this UUID. 
    long timestamp() 
     The timestamp value associated with this UUID. 

更多细节在这里:http://docs.oracle.com/javase/1.5.0/docs/api/java/util/UUID.html

当搜索我碰到来到ULIB解决 (通用唯一字典顺序可排序的标识符) https://github.com/huxi/sulky/tree/master/sulky-ulid/

它不长,但较短然后UUID。

一个ULID:

  • 是用UUID兼容/ GUID的 1每毫秒21E + 24个独特ULIDs(1,208,925,819,614,629,174,706,176是精确的)
  • 按字典顺序排序
  • 规范地编码为一个26字符的字符串,而不是在36字符UUID
  • 用途Crockford的base32,以便提高效率和可读性(5个比特每个字符)
  • 不区分大小写
  • 没有特殊字符(URL安全)