ThreadLocalRandom als schneller paralleler Zufallszahlengenerator

Zufallszahlen sind immer nur Pseudozufallszahlen und werden mit einer mathematischen Formel aus dem Vorgänger generiert. Der Vorgänger muss dabei gespeichert werden, und das ist die Aufgabe eines Random-Objekts. Die Methode Math.random() nutzt intern ein Random-Objekt, und jetzt kann es zu Wartezeiten kommen, wenn mehrere Threads gleichzeitig random() aufrufen, denn die Methode darf intern ja nur einen Thread die letzte Zufallszahl schreiben lassen. Math ist also eine Klasse mit Zustand und Zustandsverwaltung ist bei Multithreaded-Anwendungen immer etwas speziell.

Um Zufallszahlen schnell generieren zu können, sind diese Verzögerungen ungünstig, und es gibt zwei Lösungen dafür. Einmal lässt sich pro Thread ein Random-Objekt generieren, sodass es im Code der Random-Klasse dann keine Konkurrenzsituation geben kann. Aber optimal ist das noch nicht, denn der Programmcode der Random-Klasse ist auf diese Nebenläufigkeit vorbereitet, und bei nur einem Thread wäre ein schlankerer Programmcode besser, der für eine Single-Threaded Abarbeitung optimiert ist. Und hier kommt die Klasse java.util.concurrent.ThreadLocalRandom ins Spiel. Sie ist eine Unterklasse von Random und überschreibt die eigentliche Generator-Methode next(int)-Methode so, dass es keine Synchronisation gibt; die Ausführung in Multithreaded-Umgebung ist dementsprechend schnell.

Beispiel: Erzeuge Zufallszahlen zwischen 1 und 10:

ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
System.out.println( threadLocalRandom.nextInt( 1, 10 + 1 ) );
System.out.println( threadLocalRandom.nextInt( 1, 10 + 1 ) );

Die Variable threadLocalRandom kann problemlos zwischen verschiedenen Threads „geteilt“ werden.

Die Klasse ThreadLocalRandom erbt alle Methoden von Random, und überschreibt etwa die neuen Methoden aus Java 8, die einen Stream von Zufallszahlen liefern. Desweiteren kommen einige neue Methoden hinzu, um etwa Zufallszahlen in einem gewissen Bereich zu generieren – das fehlt in Random. Ein neuer Seed kann nicht gesetzt werden, ThreadLocalRandom überschreibt setSeed(long) so, dass eine UnsupportedOperationException ausgelöst wird.

class java.util.concurrent.ThreadLocalRandom
extends Random

§ static ThreadLocalRandom current()
Liefert das aktuelle ThreadLocalRandom-Objekt.

§ void setSeed(long seed)
Nicht unterstützt, löst UnsupportedOperationException aus.

§ double nextDouble(double n)

§ double nextDouble(double least, double bound)

§ double nextGaussian()

§ int nextInt(int least, int bound)

§ long nextLong(long n)

§ long nextLong(long least, long bound)
Liefert Zufallszahl und aktualisiert den Seed.

§ DoubleStream doubles()

§ IntStream ints()

§ LongStream longs()

§ DoubleStream gaussians()
Liefert einen Stream von Daten.

§ protected int next(int bits)
Liefert die nächste Zufallszahl, eine interne Methode, die ThreadLocalRandom aus Random überschreibt und protected belässt.

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert