我需要在Java中创建一个时间戳(以毫秒为单位),该时间戳保证在该特定VM实例中是唯一的。即需要一些方法来限制System.currentTimeMillis()的吞吐量,这样它每ms最多返回一个结果。关于如何实现的任何想法?
答案 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:
答案 3 :(得分:1)
您可以使用System.nanoTime()
,这是最精确的可用系统计时器,并将其除以百万以获得毫秒。虽然没有正式保证更新的频率,但我认为有理由认为它更频繁地更新(数量级),而不是每毫秒更新一次。当然,如果以小于毫秒的间隔创建整数时间戳,那么它们不可能都是唯一的。
请注意,绝对值nanoTime()
是任意的。如果你想要绝对时间,请以某种方式进行校准,即在开始时将其与currentTimeMillis()
进行比较。
答案 4 :(得分: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