Creating a unique timestamp in Java
Asked Answered
R

5

15

I need to create a timestamp (in milliseconds) in Java that is guaranteed to be unique in that particular VM-instance. I.e. need some way to throttle the throughput of System.currentTimeMillis() so that it returns at most one results every ms. Any ideas on how to implement that?

Roye answered 8/2, 2012 at 10:13 Comment(2)
I'm not sure what do you mean throttling currentTimeMillis() so that it returns at most one result every ms? If you want unique timestamps, you'd rather like to guarantee that it returns a different value at each call, right?Puryear
Do they have to be monotonically increasing? Do they have to bear any relationship with actual time? Do they have to be unique across multiple runs at all?Mccaslin
B
43

This will give a time as close the current time as possible without duplicates.

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;
    }
}

One way to avoid the limitation of one id per milli-second is to use a micro-second timestamp. i.e. multiply currentTimeMS by 1000. This will allow 1000 ids per milli-second.

Note: if time goes backwards, eg due to an NTP correction, the time will just progress at 1 milli-second per invocation until time catches up. ;)

Brittaniebrittany answered 8/2, 2012 at 10:20 Comment(2)
Used correctly, this will mean you will have unique ids even after restarting your application.Brittaniebrittany
You don't exceed an average of 1 per milli-second or 1000 per milli-second (depending on what your multiple is) This way by the time you restart, the id will be greater than the last id used before the application stopped. Given you can make the factor anything you want, this shouldn't be a problem. I use a nano-time basic id. ;)Brittaniebrittany
F
4

You can use System.nanoTime() for better accuracy

Although I tried below and each time it gives different values, it probably is not guaranteed to be unique all the time.

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);
    }

Another way is to use AtomicInteger/AtomicLong classes for unique numbers if the time is not important for you and you just need unique number, this probably is a btter choice.

Focus answered 8/2, 2012 at 10:22 Comment(4)
nanoTime is monotonic, but not always unique. You can get lots of duplicates. e.g. on Red Hat & Centos 5.x the resolution is micro-second, so you get lots of repeated values.Brittaniebrittany
Thanks for the info. I guessed it depends on the OS and the machine.Focus
You can use nanoTime with a check that its different. (Similar to my solution) The nanoTime is the uptime in ano-seconds on many systems.Brittaniebrittany
+1: Done the same for you answer as you can use nanoTime with AtomicLong (not AtomicInteger)Brittaniebrittany
I
2

While searching for a solution I came across ULIB (Universally Unique Lexicographically Sortable Identifier) https://github.com/huxi/sulky/tree/master/sulky-ulid/

It's not a long, but shorter then UUID.

A ULID:

  • Is compatible with UUID/GUID's 1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)
  • Lexicographically sortable
  • Canonically encoded as a 26 character string, as opposed to the 36 character UUID
  • Uses Crockford's base32 for better efficiency and readability (5 bits per character)
  • Case insensitive
  • No special characters (URL safe)
Interlingua answered 22/12, 2017 at 8:58 Comment(0)
P
1

You could use System.nanoTime(), which is the most precise available system timer, and divide that by million to get milliseconds. While there are no formal guarantees on how often it's updated, I believe it's reasonable to assume that it updates way more (order(s) of magnitude) frequently than once per millisecond. Of course, if you create integer timestamps by less than millisecond interval, then they can't all be unique.

Note that the absolute value nanoTime() is arbitrary. If you want absolute time, calibrate it somehow, i.e. compare it to currentTimeMillis() when starting.

Puryear answered 8/2, 2012 at 10:22 Comment(0)
G
0

Could you perhaps make use of java.util.UUID and it's timestamp() and clockSequence()?

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

More details here: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/UUID.html

Garrotte answered 8/2, 2012 at 10:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.