0

this is a short lived app with no db and only keeping Mapping of original->shorten in memory. If I have following scala method which gets called everytime, to generate a value (which is then used as a shorten URL) and then kept in a Map(originalUrl->shortenUrl. choosing from 4.2 billion(Integer.MAX_VALUE) possibles with redix 36. Any downside of the approach for generating unique shorten URL values if called in a multi-threaded environment?

def randomUrl: String = {
   Integer.toString(new Random().nextInt(Integer.MAX_VALUE), 36)
}
user2066049
  • 1,371
  • 1
  • 12
  • 26
  • 1
    From the java page for Random (what Scala wraps, I just checked the source): "This constructor sets the seed of the random number generator to a value very likely to be distinct from any other invocation of this constructor." So your seed *should* be fine – Millie Smith Mar 13 '14 at 16:26
  • @MillieSmith default seed value is `System.currentTimeMillis` so it wouldn't be okay if you spawn multiple threads **precisely** at the same time – om-nom-nom Mar 13 '14 at 16:52
  • @user2066049 disregard my first comment, I was looking at the wrong source code :-( – om-nom-nom Mar 13 '14 at 16:56

2 Answers2

1

You should not have any problems. The following one liner is the Scala Random constructor.

def this() = this(new java.util.Random())

The OpenJDK source code for the default constructor does use System.nanoTime(), but it does more than just use the time. It uses an AtomicLong and calls compareAndSet (an atomic operation) to set a new value. This atomic operation is thread-safe. If the value has already been set by another thread, it will retry for another AtomicLong value to make your seed unique.

public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}
Community
  • 1
  • 1
Millie Smith
  • 4,536
  • 2
  • 24
  • 60
0

Non-uniqueness will likely be a problem with only 31 bits of information. You will expect your first collisions after only around 64k URLs generated. Use more bits. And you can't ensure that your seeds will be different with that approach, so you're better off creating one source of random numbers and sharing it.

java.util.Random is threadsafe, and Scala just forwards to the Java implementation, so you should be fine in terms of thread safety even if you don't create a new Random each call.

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407