How to create a 64 bit Unique Integer in Java

谁都会走 提交于 2019-12-03 20:29:40
Peter Lawrey

If you need the numbers to be unique in one process, robust between restarts, you can use a simple AtomicLong and a timer.

private static final AtomicLong TS = new AtomicLong();
public static long getUniqueTimestamp() {
    long micros = System.currentTimeMillis() * 1000;
    for ( ; ; ) {
        long value = TS.get();
        if (micros <= value)
            micros = value + 1;
        if (TS.compareAndSet(value, micros))
            return micros;
    }
}

This will give you a unique "timestamp" with a millisecond accuracy but can only handle 1000 ids per millisecond without getting ahead of the actual time. This works fine on restart as the time will jump past previous values (again assuming you have less than one million per second on average)

Use a HashSet in order to ensure uniqueness of the values you're storing. You can then check whether the insert was successful by checking what add returns. If the values have to be 'randomised' you can use your own algorithm, or check out SecureRandom.

Long getUniqueNumber(HashSet uniqueNumberSet) {
    Long unique = generateUniqueNumber();
    if(!uniqueNumberSet.add(unique)) { // handle collision }
    return unique;
}

As Marc B said, the best approach is a simple long which is initialized with zero and incremented every time you need a new value.

If you need concurrency, or if performance is not an issue at all, then you can use AtomicLong as suggested by Loc Ha; however, if you really need it to be a long and not an int, then I suspect you are going to be generating lots of them, so you should probably avoid the extra overhead of AtomicLong unless you are sure you also need concurrency.

System.nanoTime() is not a good idea, as you have no guarantee that two consecutive calls to it will always yield different values.

EDIT (to cover update in question)

No, the timestamp part of the UUID is not guaranteed to be unique, for precisely the same reasons that System.nanoTime() is not guaranteed to be unique. If the timestamp of the UUID was unique, then there would be no need to have a UUID type, we would just always use that timestamp part. Time is always a bad way to go about guaranteeing uniqueness.

You want to get unique ID, the appropriate way(although 128 bit):

UUID.randomUUID();

A bit less appropriate(collisions* are possible) with 64 bits:

UUID.getLeastSignificantBits();
UUID.getMostSignificantBits();

To really get unique ID(if they are critical to your operation):

  1. Use centralised storage of all IDs
  2. When you need an ID, let this centralised system handle it -> DB and auto incremented values are usually the easiest way

*collisions => 2 or more equal values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!