Est-il valide de partager une instance de la Random
classe entre plusieurs threads? Et pour appeler à nextInt(int)
partir de plusieurs threads en particulier?
java.util.concurrent.ThreadLocalRandom
.
Est-il valide de partager une instance de la Random
classe entre plusieurs threads? Et pour appeler à nextInt(int)
partir de plusieurs threads en particulier?
java.util.concurrent.ThreadLocalRandom
.
Réponses:
Il est thread-safe dans le sens où il génère toujours des nombres aléatoires lorsqu'il est utilisé par plusieurs threads.
L'implémentation de la JVM Sun / Oracle utilise synchronized et AtomicLong comme amorce pour améliorer la cohérence entre les threads. Mais cela ne semble pas être garanti sur toutes les plates-formes dans la documentation.
Je n'écrirais pas votre programme pour exiger une telle garantie, d'autant plus que vous ne pouvez pas déterminer l'ordre dans lequel nextInt()
sera appelé.
C'est thread-safe, bien que ce ne soit pas toujours le cas.
Voir http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 pour plus de détails.
Selon la documentation, Math.random () garantit qu'il est sûr pour une utilisation par plusieurs threads. Mais pas la classe Random. Je suppose que vous devrez alors synchroniser cela vous-même.
Oui, Random est thread-safe. la nextInt()
méthode appelle la next(int)
méthode protégée qui utilise AtomicLong seed, nextseed
(atomic long) pour générer une graine suivante. AtomicLong
est utilisé pour la sécurité des threads lors de la génération de semences.
Comme dit, il s'agit d'une sauvegarde de thread, mais il peut être judicieux d'utiliser java.util.concurrent.ThreadLocalRandom
selon cet article (lien mort). ThreadLocalRandom est également une sous-classe de Random, il est donc rétrocompatible.
L'article Linked a comparé les résultats de profilage des différentes classes au hasard:
java.util.Random
,java.util.concurrent.ThreadLocalRandom
etjava.lang.ThreadLocal<java.util.Random>
. Les résultats ont montré que l'utilisation de ThreadLocalRandom est la plus performante, suivie de ThreadLocal et de la pire performance Random lui-même.
Il n'y a aucune raison pour laquelle plusieurs threads ne peuvent pas tous utiliser le même Random. Cependant, puisque la classe n'est pas explicitement thread-safe et maintient une séquence de nombres pseudo-aléatoires via la graine. Plusieurs threads peuvent se retrouver avec le même nombre aléatoire. Il serait préférable de créer plusieurs aléas pour chaque thread et de les semer différemment.
EDIT : Je viens de remarquer que l'implémentation Sun utilise AtomicLong, donc je suppose que c'est Thread-safe (comme l'a également noté Peter Lawrey (+1)).
EDIT2 : OpenJDK utilise également AtomicLong pour la graine. Comme d'autres l'ont dit, il n'est toujours pas bon de se fier à cela.
Voici comment j'ai traité le problème sans supposer que Random utilise des variables atomiques. Il peut encore entrer en collision de manière aléatoire si elle currentTime * thread id
est égale dans le futur, mais c'est assez rare pour mes besoins. Pour vraiment éviter la possibilité de collisions, vous pouvez demander à chaque demande d'attendre un horodatage d'horloge unique.
/**
* 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)
partie est -elle significative?
(24*60*60*1000)
était de sorte qu'un fil d'ID 12
à xxxxxxxxxx045
Millis ne s'ensemencée même comme un fil 22
à xxxxxxxxxx035
Millis. Cependant, je n'ai aucune bonne raison de supposer que les ID de threads sont incrémentiels, et il n'y a aucune bonne raison de penser que je crée des threads à des moments plus aléatoires demain qu'aujourd'hui. J'ai simplifié l'alg maintenant et mis à jour la description pour identifier le défaut.
La Random
classe n'est pas configurée pour qu'une instance soit utilisée dans plusieurs threads. Bien sûr, si vous faites cela, vous augmenterez probablement la possibilité de devenir imprévisible et plus proche des nombres aléatoires . Mais comme il s'agit d'un générateur pseudo-aléatoire, je ne vois pas pourquoi vous auriez besoin de partager une instance. Existe-t-il une exigence plus spécifique?