4
\$\begingroup\$

I need to generate a 64 bit unique integer in Java. I need to make sure that there is very few or no collisions if possible.

I came up with the below code which works fine:

public class TestUniqueness {

    private static final AtomicLong TS = new AtomicLong();

    public static void main(String[] args) {
        // for testing, just added the for loop
        for (int i = 1; i <= 100000; i++) {
            System.out.println(getUniqueTimestamp());
        }
    }

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

I will be running the above code in production.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ What do you mean by a "unique" integer? \$\endgroup\$ Feb 6, 2015 at 23:10
  • \$\begingroup\$ This is tagged random but you are just getting the current time without repeats, which doesn't qualify as random in my book. \$\endgroup\$ Feb 7, 2015 at 0:02
  • 3
    \$\begingroup\$ In short, what are your specifications, and how does a simple incrementing counter not satisfy them? \$\endgroup\$ Feb 7, 2015 at 0:03
  • \$\begingroup\$ @PierreMenard My specification is only to generate the 64 bit unique integer, that's it. If it is random, then that is also fine. \$\endgroup\$
    – david
    Feb 7, 2015 at 0:06
  • 1
    \$\begingroup\$ System.nanoTime() (Don't see relation to tag random) \$\endgroup\$
    – greybeard
    Jan 10, 2016 at 7:05

3 Answers 3

12
\$\begingroup\$

My specification is only to generate the 64 bit unique integer, that's it.

In this case, there's no need for anything more complicated than atomically incrementing a counter:

public class Counter {

    private static final AtomicLong counter = new AtomicLong(0);

    public static long getNextNumber(){
        return counter.incrementAndGet();
    }
}

To offer a more specific critique of your code, it's unnecessarily complicated and inefficient. I don't see anything incorrect about it (i.e. it seems like it meets your criteria), but there's the old saying about obviously no bugs vs no obvious bugs (paraphrased).

\$\endgroup\$
2
  • \$\begingroup\$ If this is a code that runs in a server that can go down and needs to be restarted, then I think that it would be good to set the initial time of AtomicLong to the current system time. In that way, when the server is restarted, it does not even repeat on values that it generated before being restarted. \$\endgroup\$
    – ASDF
    Sep 15, 2015 at 17:18
  • 1
    \$\begingroup\$ @JadieldeArmas That won't work, you will get conflicts eventually. If you're incrementing from a timestamp, and then restart in the future, the new starting timestamp has a chance of being a number you previously used. It's much better to lookup the last max value and then restart from there. \$\endgroup\$ Jan 10, 2017 at 21:48
3
\$\begingroup\$

Just some points:

for (;;) {
    long value = TS.get();
    if (micros <= value)
        micros = value + 1;
    if (TS.compareAndSet(value, micros))
        return micros;
}

Here, I suggest you do while(true) instead of for(;;). It is a matter of preference, but I think while(true) is easier to understand.


Also, always put braces for if statements. If you don't, horrible bugs may occur. Here is an example:

Say you have this if statement:

if(isSomething())
    doSomething();

And then you decide that the code has to do something else in the if statement:

if(isSomething())
    doSomething();
    doSomethingElse();

Now you have a horrible bug. It looks fine, but when you run it, doSomethingElse() will execute no matter what isSomething() returns. If you actually had braces:

if(isSomething()) {
    doSomething();
}

Then:

if(isSomething()) {
    doSomething();
    doSomethingElse();
}

That should work fine.

\$\endgroup\$
1
\$\begingroup\$

Is there any reason why you are not using the Apache library?

The RandomStringsUtils library provides a method for creating a random number.

The best part: you specify the range.

Library

By the way, the method is randomNumber()

\$\endgroup\$
1
  • \$\begingroup\$ Looks ok, but I need to have uniqueness. Random doesn't mean unique. \$\endgroup\$
    – david
    Feb 6, 2015 at 22:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.