在Java中创建唯一的时间戳

问题描述 投票:12回答:5

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

java concurrency timestamp epoch throttling
5个回答
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毫秒的速度进行,直到时间赶上。 ;)


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
投票

在寻找解决方案的同时,我遇到了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安全)

1
投票

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

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


0
投票

你能否利用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

© www.soinside.com 2019 - 2024. All rights reserved.