在Java中创建唯一的时间戳

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

这将给出尽可能接近当前时间的时间而不重复。

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 ids。

注意:如果时间倒退,例如由于NTP校正,时间将在每次调用时以1毫秒的速度进行,直到时间赶上。 ;)

您可以使用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类来获取唯一数字,如果时间对您来说并不重要,并且您只需要唯一的数字,这可能是一个不错的选择。

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

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

在寻找解决方案时,我遇到了ULIB (通用唯一字典排序标识符) https://github.com/huxi/sulky/tree/master/sulky-ulid/

它不是很长,但比UUID短。

ULID:

  • 与UUID / GUID的每毫秒1.21e + 24个唯一ULID兼容(确切地说是1,208,925,819,614,629,174,706,176)
  • 按字典顺序排序
  • 典型编码为26个字符的字符串,而不是36个字符的UUID
  • 使用Crockford的base32以提高效率和可读性(每个字符5位)
  • 不区分大小写
  • 没有特殊字符(URL安全)

您是否可以使用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