Ist es gültig, eine Instanz der Random
Klasse für mehrere Threads freizugeben? Und nextInt(int)
insbesondere aus mehreren Threads aufzurufen ?
java.util.concurrent.ThreadLocalRandom
.
Ist es gültig, eine Instanz der Random
Klasse für mehrere Threads freizugeben? Und nextInt(int)
insbesondere aus mehreren Threads aufzurufen ?
java.util.concurrent.ThreadLocalRandom
.
Antworten:
Es ist threadsicher in dem Sinne, dass es bei Verwendung durch mehrere Threads immer noch Zufallszahlen generiert.
Die Sun / Oracle JVM-Implementierung verwendet synchronisiert und AtomicLong als Startwert, um die Konsistenz zwischen den Threads zu verbessern. Es scheint jedoch nicht für alle Plattformen in der Dokumentation garantiert zu sein.
Ich würde Ihr Programm nicht schreiben, um eine solche Garantie zu verlangen, zumal Sie die Reihenfolge, in der nextInt()
aufgerufen wird, nicht bestimmen können .
Es ist threadsicher, obwohl es nicht immer war.
Weitere Informationen finden Sie unter http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 .
Gemäß der Dokumentation garantiert Math.random () , dass es für die Verwendung durch mehrere Threads sicher ist. Die Zufallsklasse tut dies jedoch nicht. Ich würde davon ausgehen, dass Sie das selbst synchronisieren müssen.
Ja, Random ist threadsicher. Die nextInt()
Methode ruft die geschützte next(int)
Methode auf, die AtomicLong seed, nextseed
(atomar lang) verwendet, um einen nächsten Startwert zu generieren. AtomicLong
wird zur Gewindesicherheit bei der Samenerzeugung verwendet.
Wie gesagt, es ist Thread-sicher, aber es kann ratsam sein, java.util.concurrent.ThreadLocalRandom
gemäß diesem Artikel zu verwenden (Link tot). ThreadLocalRandom ist ebenfalls eine Unterklasse von Random und daher abwärtskompatibel.
Der Artikel verlinkte verglichenen Profilierungs Ergebnisse der verschiedenen Zufalls Klassen:
java.util.Random
,java.util.concurrent.ThreadLocalRandom
undjava.lang.ThreadLocal<java.util.Random>
. Die Ergebnisse zeigten, dass die Verwendung von ThreadLocalRandom am leistungsfähigsten ist, gefolgt von ThreadLocal und Random mit der schlechtesten Leistung.
Es gibt keinen Grund, warum mehrere Threads nicht alle denselben Zufall verwenden können. Da die Klasse jedoch nicht explizit threadsicher ist und eine Folge von Pseudozufallszahlen über den Startwert beibehält. Mehrere Threads können dieselbe Zufallszahl haben. Es wäre besser, mehrere Zufälle für jeden Thread zu erstellen und sie unterschiedlich zu setzen.
EDIT : Ich habe gerade bemerkt, dass die Sun-Implementierung AtomicLong verwendet, also denke ich, dass dies Thread-sicher ist (wie auch von Peter Lawrey (+1) bemerkt).
EDIT2 : OpenJDK verwendet auch AtomicLong für den Startwert. Wie andere gesagt haben, ist es immer noch nicht gut, sich darauf zu verlassen.
Hier ist, wie ich mit dem Problem umgegangen bin, ohne anzunehmen, dass Random atomare Variablen verwendet. Es kann immer noch zufällig kollidieren, wenn currentTime * thread id
es irgendwann in der Zukunft gleich ist, aber das ist selten genug für meine Bedürfnisse. Um Kollisionsmöglichkeiten wirklich zu vermeiden, kann jede Anforderung auf einen eindeutigen Zeitstempel warten.
/**
* 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)
Teil von Bedeutung?
(24*60*60*1000)
war so, dass ein Thread mit der ID 12
bei xxxxxxxxxx045
Millis nicht wie ein Thread 22
bei xxxxxxxxxx035
Millis ausgesät wurde. Ich habe jedoch keinen guten Grund anzunehmen, dass Thread-IDs inkrementell sind, und es gibt keinen guten Grund zu der Annahme, dass ich morgen zu mehr zufälligen Zeiten als heute Threads erstelle. Ich habe die Alge jetzt vereinfacht und die Beschreibung aktualisiert, um das Manko zu identifizieren.
Die Random
Klasse ist nicht für eine Instanz eingerichtet, die in mehreren Threads verwendet werden soll. Wenn Sie dies tun, erhöhen Sie natürlich wahrscheinlich die Wahrscheinlichkeit, unvorhersehbar zu werden und Zufallszahlen näher zu kommen . Da es sich jedoch um einen Pseudozufallsgenerator handelt, kann ich nicht erkennen, warum Sie eine Instanz gemeinsam nutzen müssen. Gibt es eine spezifischere Anforderung?