Могу ли я использовать nanoTime вместо randomUUID? - PullRequest
0 голосов
/ 28 июня 2019

Я пишу процесс, который возвращает данные подписчикам каждые несколько секунд. Я хотел бы создать уникальный идентификатор для подписчиков:

producer -> subsriber1
         -> subsriber2

В чем разница между использованием:

  • java.util.UUID.randomUUID()
  • System.nanoTime()
  • System.currentTimeMillis()

Будет ли нано время всегда уникальным? А как насчет случайного UUID?

Ответы [ 3 ]

2 голосов
/ 28 июня 2019

UUID

128-битный UUID был изобретен именно для вашей цели: Генерация идентификаторов на одной или нескольких машинах без координации через центральный орган.

В идеале вы должны использовать исходный UUID версии 1 или его варианты в версиях 2, 3 и 5. Оригинал берет MAC-адрес сетевого интерфейса хост-компьютера и объединяет его с текущим моментом плюс небольшое произвольное число, которое увеличивается, когда часы хоста настроены. Такой подход устраняет любые практические проблемы для дубликатов.

Java не связывает реализацию для генерации этих версий. Я предполагаю, что у разработчиков Java были проблемы с конфиденциальностью и безопасностью, касающиеся разглашения места, времени и MAC-адреса.

Java поставляется только с одной реализацией генератора для версии 4. В этом типе все, кроме 6, из 128 битов генерируются случайным образом. Если используется криптографически сильный генератор случайных чисел, эта версия достаточно хороша для использования в большинстве распространенных ситуаций, не заботясь о столкновениях.

Поймите, что 122 бита - это действительно большой диапазон чисел (5.316911983139664e + 36). 64-битные значения дают диапазон 18 446 744 073 709 552 000 (18 квинтиллионов). Остальные 58 бит (122-64 = 58) дают диапазон чисел 288,230,376,151,711,740 (288 квадриллионов). Теперь умножьте эти два числа, чтобы получить диапазон 122-бит: 2 ^ 122 = (18,446,744,073,709,552,000 * 288,230,376,151,711,740), что составляет 5,3 ундециллион .

Тем не менее, если у вас есть доступ к генерации версии UUID, отличной от 4, используйте ее. Например, в системе базы данных, такой как Postgres , сервер базы данных может генерировать номера UUID в различных версиях, включая версию 1. Или вы можете найти библиотеку Java для генерации таких UUID, хотя эта библиотека может не быть платформой -независимый (он может иметь собственный код внутри).

System.nanoTime

Имейте в виду, что System.nanoTime не имеет ничего , имеющего отношение к текущей дате и времени. Процитирую Javadoc:

Этот метод может использоваться только для измерения прошедшего времени и не связан с каким-либо другим понятием системного или настенного времени.

Функция System.nanoTime просто возвращает число long, число наносекунд с некоторого происхождения, но это происхождение , а не , указанное .

Единственное обещание, данное в спецификации Java, заключается в том, что источник не изменится во время выполнения JVM. Таким образом, вы знаете, что число постоянно увеличивается во время выполнения вашего приложения. Если не достигнуто ограничение в long, когда счетчик будет опрокидываться. Этот ролловер может занять 292 года (2 ^ 63 наносекунды), если источник равен нулю, но, опять же, источник не указан.

По моему опыту работы с конкретными реализациями Java, которые я использовал, источником является момент запуска JVM. Это означает, что я наверняка увижу одни и те же цифры снова и снова после следующего перезапуска JVM.

Так что использование System.nanoTime в качестве идентификатора - плохой выбор. Если ваше приложение случайно совпадет с тем же самым наносекундным числом, как и в предыдущем запуске, это чистый шанс, но шанс, который вам не нужно использовать. Вместо этого используйте UUID.

1 голос
/ 29 июня 2019

java.util.UUID.randomUUID () потенциально поточно-ориентированный .

Не безопасно сравнивать результаты вызовов System.nanoTime () между различными потоками. Если в течение одной миллисекунды выполняется много потоков, эта функция возвращает одинаковые миллисекунды.

То же самое относится и к System.currentTimeMillis () также.

Сравнивая System.currentTimeMillis () и System.nanoTime (), последний более дорогой, так как он требует больше циклов ЦП, но и более точен. Таким образом, UUID должен служить вашей цели.

0 голосов
/ 28 июня 2019

Я думаю, что да, вы можете использовать System.nanoTime() как id. Я проверил это и не столкнулся с дублированием. P.S. Но я настоятельно рекомендую вам использовать UUID.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...