¿Es válido compartir una instancia de la Random
clase entre varios subprocesos? ¿Y para llamar nextInt(int)
desde múltiples hilos en particular?
java.util.concurrent.ThreadLocalRandom
.
¿Es válido compartir una instancia de la Random
clase entre varios subprocesos? ¿Y para llamar nextInt(int)
desde múltiples hilos en particular?
java.util.concurrent.ThreadLocalRandom
.
Respuestas:
Es seguro para subprocesos en el sentido de que aún generará números aleatorios cuando sea utilizado por varios subprocesos.
La implementación de Sun / Oracle JVM utiliza sincronizados y AtomicLong como semilla para mejorar la coherencia entre los subprocesos. Pero no parece estar garantizado en todas las plataformas en la documentación.
No escribiría su programa para requerir tal garantía, especialmente porque no puede determinar el orden en el que nextInt()
se llamará.
Es seguro para subprocesos, aunque no siempre lo fue.
Consulte http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 para obtener más detalles.
Según la documentación, Math.random () garantiza que es seguro para su uso por varios subprocesos. Pero la clase Random no lo hace. Supongo que entonces tendrás que sincronizarlo tú mismo.
Sí, Random es seguro para subprocesos. el nextInt()
método llama al next(int)
método protegido que usa AtomicLong seed, nextseed
(atomic long) para generar una siguiente semilla. AtomicLong
se utiliza para la seguridad de subprocesos en la generación de semillas.
Como se dijo, se guarda en subprocesos, pero puede ser aconsejable usarlo de java.util.concurrent.ThreadLocalRandom
acuerdo con este artículo (enlace muerto). ThreadLocalRandom también es una subclase de Random, por lo que es compatible con versiones anteriores.
El artículo enlazado compararon los resultados de las diferentes clases de perfiles de azar:
java.util.Random
,java.util.concurrent.ThreadLocalRandom
yjava.lang.ThreadLocal<java.util.Random>
. Los resultados mostraron que el uso de ThreadLocalRandom es más eficaz, seguido de ThreadLocal y Random con peor rendimiento.
No hay ninguna razón por la que varios subprocesos no puedan usar el mismo Random. Sin embargo, dado que la clase no es explícitamente segura para subprocesos y mantiene una secuencia de números pseudoaleatorios a través de la semilla. Varios subprocesos pueden terminar con el mismo número aleatorio. Sería mejor crear varios Randoms para cada hilo y sembrarlos de manera diferente.
EDITAR : Acabo de notar que la implementación de Sun usa AtomicLong, así que supongo que es seguro para subprocesos (como también lo señaló Peter Lawrey (+1)).
EDIT2 : OpenJDK también usa AtomicLong para la semilla. Como han dicho otros, todavía no es bueno confiar en esto.
Así es como manejé el problema sin asumir que Random usa variables atómicas. Todavía puede colisionar aleatoriamente si currentTime * thread id
es igual en algún momento en el futuro, pero eso es lo suficientemente raro para mis necesidades. Para evitar realmente la posibilidad de colisiones, puede hacer que cada solicitud espere una marca de tiempo de reloj única.
/**
* Thread-specific random number generators. Each is seeded with the thread
* ID, so the sequence of pseudo-random numbers are unique between threads.
*/
private static ThreadLocal<Random> random = new ThreadLocal<Random>() {
@Override
protected Random initialValue() {
return new Random(
System.currentTimeMillis() *
Thread.currentThread().getId());
}
};
(24*60*60*1000)
parte significativa?
(24*60*60*1000)
fue que un hilo con ID 12
en xxxxxxxxxx045
millis no se sembró de la misma manera que un hilo 22
en xxxxxxxxxx035
millis. Sin embargo, no tengo ninguna buena razón para suponer que los ID de subprocesos son incrementales, y no hay una buena razón para pensar que estoy creando subprocesos en momentos más aleatorios mañana que hoy. Simplifiqué el alg ahora y actualicé la descripción para identificar la deficiencia.
La Random
clase no está configurada para que una instancia se utilice en varios subprocesos. Por supuesto, si hizo esto, probablemente aumentará la posibilidad de volverse impredecible y más cercano a números aleatorios . Pero dado que es un generador pseudoaleatorio, no veo por qué necesitarías compartir una instancia. ¿Existe algún requisito más específico?