在Java中创建唯一的时间戳

时间:2012-02-08 10:13:23

标签: java concurrency timestamp epoch throttling

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

5 个答案:

答案 0 :(得分:35)

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

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毫秒的速度进行,直到时间赶上。 ;)

答案 1 :(得分:4)

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

答案 2 :(得分:2)

在搜索解决方案时,我遇到了 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位)
  • 不区分大小写
  • 没有特殊字符(网址安全)

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

您是否可以使用java.util.UUIDtimestamp()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