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\$
  • 1
    \$\begingroup\$ What do you mean by a "unique" integer? \$\endgroup\$ – 200_success Feb 6 '15 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\$ – Pierre Menard Feb 7 '15 at 0:02
  • 3
    \$\begingroup\$ In short, what are your specifications, and how does a simple incrementing counter not satisfy them? \$\endgroup\$ – Pierre Menard Feb 7 '15 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 '15 at 0:06
  • 1
    \$\begingroup\$ System.nanoTime() (Don't see relation to tag random) \$\endgroup\$ – greybeard Jan 10 '16 at 7:05
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\$
  • \$\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\$ – Jadiel de Armas Sep 15 '15 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\$ – Mani Gandham Jan 10 '17 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\$
  • \$\begingroup\$ Looks ok, but I need to have uniqueness. Random doesn't mean unique. \$\endgroup\$ – david Feb 6 '15 at 22:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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