2014-03-13 2 views
0

это короткое живое приложение без дБ и сохранение Картинга оригинала -> сокращение в памяти. Если у меня есть метод scala, который вызывается каждый раз, чтобы генерировать значение (которое затем используется как сокращенный URL-адрес), а затем сохраняется на карте (originalUrl-> shortenUrl. Выбор из 4.2 миллиардов (Integer.MAX_VALUE) возможен с redix 36 . Любой недостаток подхода для генерации уникальных значений укоротить URL при вызове в многопоточной среде?Base36 Случайное число

def randomUrl: String = { 
    Integer.toString(new Random().nextInt(Integer.MAX_VALUE), 36) 
} 
+1

На странице Java для Random (что оборачивает Scala, я только что проверил источник): «Этот конструктор устанавливает семя генератора случайных чисел до величины, весьма вероятно, чтобы быть отличными от любого другого вызова этого конструктора «. Таким образом, ваше семя * должно * быть хорошим –

+0

@MillieSmith значение по умолчанию - 'System.currentTimeMillis', поэтому было бы не так, если бы вы породили несколько потоков ** точно ** в то же время –

+0

@ user2066049 игнорировать мой первый комментарий, я искал неправильный исходный код :-( –

ответ

0

Неединственность, вероятно, будет проблема только с 31 битами информации. Вы будете ожидать ваши первые столкновения после генерируется только около 64 тыс. URL-адресов. Используйте больше битов, и вы не можете гарантировать, что ваши семена будут отличаться от этого подхода, поэтому вам лучше создать один источник случайных чисел и поделиться им.

java.util.Random является потокобезопасным, а Scala просто переходит к реализации Java, поэтому вам должно быть хорошо с точки зрения безопасности потоков, даже если вы не создаете новый Random для каждого вызова.

+0

Вы предлагаете использовать Long вместо этого? – user2066049

+0

@ user2066049 - По крайней мере, или вы могли бы сгенерировать, а затем подтвердить, что он действительно уникален. Если нет, просто сгенерируйте снова. –

1

У вас не должно быть никаких проблем. Следующий один вкладыш - это конструктор Scala Random.

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

Исходный код OpenJDK для конструктора по умолчанию действительно использует System.nanoTime(), но это больше, чем просто использовать время. Он использует AtomicLong и вызывает compareAndSet (атомная операция) для установки нового значения. This atomic operation is thread-safe. Если значение уже задано другим потоком, оно повторит попытку для другого значения AtomicLong, чтобы сделать ваше семя уникальным.

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; 
    } 
} 
Смежные вопросы