Подтвердить что ты не робот

Случайная над ThreadLocalRandom

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

Какие разногласия и, следовательно, низкая производительность? Кто-нибудь, пожалуйста, объясните мне здесь? Я не знаю, какой алгоритм входит в Random и ThreadLocalRandom, что делает их разными.

4b9b3361

Ответ 1

Это может немного помочь:

http://thoughtfuljava.blogspot.com/2012/09/prefer-threadlocalrandom-over-random.html


Цитата из источника:

Обычно для генерации случайных чисел мы либо делаем Создайте экземпляр java.util.Random OR Math.random() - который внутренне создает экземпляр java.util.Random при первом вызове. Однако в одновременных применениях использование выше приводит к проблемам конкуренции

Случайный поток является потокобезопасным для использования несколькими потоками. Но если несколько потоков используют один и тот же экземпляр Random, одно и то же семя разделяется несколькими потоками. Это приводит к конфликту между несколькими потоками и, следовательно, ухудшением производительности.

ThreadLocalRandom - решение проблемы выше. ThreadLocalRandom имеет случайный экземпляр для каждого потока и защищает от конкуренции.


Итак, в основном, используя случайный экземпляр на поток, вы можете прекратить синхронизацию семени, которая должна использоваться всеми потоками.

Ответ 2

Из документа API ThreadLocalRandom

A random number generator isolated to the current thread.  Like the
 * global {@link java.util.Random} generator used by the {@link
 * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
 * with an internally generated seed that may not otherwise be
 * modified. When applicable, use of {@code ThreadLocalRandom} rather
 * than shared {@code Random} objects in concurrent programs will
 * typically encounter much less overhead and contention.  Use of
 * {@code ThreadLocalRandom} is particularly appropriate when multiple
 * tasks (for example, each a {@link ForkJoinTask}) use random numbers
 * in parallel in thread pools.

Случайный может быть создан несколько раз/тот же случайный объект будет разделен на несколько потоков (из-за того, что он безопасен в использовании). Однако создание нескольких экземпляров одного и того же доступа к ресурсам несколькими потоками может вызвать накладные расходы.

Вместо создания экземпляра для потока и сохранения ресурса в ThreadLocal будет более совершенным. поскольку экземпляр не используется для нескольких потоков. и нет никакого публичного конструктора, вы должны использовать метод factory для его получения.

Я бы сказал, это просто factory случайных объектов, который поддерживает/кэширует экземпляр для потока.

Ответ 3

Основные алгоритмы практически одинаковы. ThreadLocalRandom использует конструкцию Java ThreadLocal для создания новой случайной переменной для каждого потока. Это гарантирует, что вызовы из каждого потока никогда не конфликтуют с каждым (без конкуренции).

Взгляните на эту строку из Random для сравнения:

  } while (!seed.compareAndSet(oldseed, nextseed));

Когда вы запрашиваете следующее значение, Random принимает старое значение и генерирует новое значение. Затем он использует функцию AtomicLong.compareAndSet для установки нового значения, только если старое значение остается тем, которое оно использовало. Если другой поток изменил значение, цикл снова запустится (и снова, пока он не станет единственным циклом, который и получит, и установит значение в генерации случайных чисел). Таким образом, существует возможная конкуренция и, следовательно, возможные последствия для производительности.

ThreadLocalRandom, поскольку он гарантированно не конфликтует, не требует атомных функций и поточно-безопасных операций/блокировки.

Есть некоторые компромиссы, о которых вы хотели бы подумать. Использование одного Random позволяет использовать один генератор случайных чисел, что очень полезно, если вы хотите использовать одно семя для вашего приложения. Если вы делаете только случайные вызовы в случайном порядке, так что конфликты, вероятно, будут "редкими" (не нормальными), тогда вы можете не беспокоиться о конфликтах, и небольшое индивидуальное воздействие на производительность может не иметь значения. Если вы вызываете случайные сотни раз в секунду для нескольких потоков, вы явно хотите использовать ThreadLocalRandom.

Ответ 4

Есть проблемы с ThreadLocalRandom, что вы не можете контролировать начальное семя. Я также не нахожу какой-либо рабочий метод семени.

Следует отметить, что существует конфликт, когда несколько потоков используют Math.random(), поскольку они будут под капотом получить доступ к общему экземпляру класса Random, есть альтернатива при использовании ThreadLocalRandom который также решает проблему семян.

ThreadLocalRandom использует семя, помещенное в поток. И они решили чтобы сделать начальное семя для вас, без каких-либо средств для его контроля. Вы может одинаково хорошо создать свой собственный экземпляр Random и использовать его в нить местной моды. Поэтому, если вы выполните следующее:

/* my thread */
rnd = new Random(my_seed);
/* use rnd */

Вы также не увидите никаких утверждений. И используя одно и то же семя, вы получаете воспроизводимый случайные последовательности, которые могут помочь в тестировании. Когда у вас несколько потоков вы можете распределять семена по этим потокам. Для создания хороших расстояний должны быть алгоритмы.

Ответ 5

Хорошо, если вы используете одну и ту же структуру данных для нескольких потоков, она обычно синхронизируется. Это дорого и требует времени. ThreadLocalRandom не нужно синхронизировать, поскольку он используется только одним потоком.

Ответ 6

Случайный экземпляр может предоставлять случайное число только одному потоку за раз. Итак, если у вас много потоков одновременно, запрашивающих случайные числа из этого экземпляра, это замедляет все потоки.

С другой стороны, каждый поток будет иметь свой собственный экземпляр ThreadLocalRandom, поэтому никакие потоки не будут блокироваться при запросе случайного числа.