All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java8.util.concurrent.ThreadLocalRandom Maven / Gradle / Ivy

/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */
package java8.util.concurrent;

import java.io.ObjectStreamField;
import java.util.Comparator;
import java.util.Random;

import java8.util.Objects;
import java8.util.Spliterator;
import java8.util.Spliterators;
import java8.util.function.Consumer;
import java8.util.function.DoubleConsumer;
import java8.util.function.IntConsumer;
import java8.util.function.LongConsumer;
import java8.util.stream.DoubleStream;
import java8.util.stream.IntStream;
import java8.util.stream.LongStream;
import java8.util.stream.StreamSupport;

/**
 * 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.
 *
 * 

Usages of this class should typically be of the form: * {@code ThreadLocalRandom.current().nextX(...)} (where * {@code X} is {@code Int}, {@code Long}, etc). * When all usages are of this form, it is never possible to * accidentally share a {@code ThreadLocalRandom} across multiple threads. * *

This class also provides additional commonly used bounded random * generation methods. * *

Instances of {@code ThreadLocalRandom} are not cryptographically * secure. Consider instead using {@link java.security.SecureRandom} * in security-sensitive applications. Additionally, * default-constructed instances do not use a cryptographically random * seed unless the {@linkplain System#getProperty system property} * {@code java.util.secureRandomSeed} is set to {@code true}. * * @since 1.7 * @author Doug Lea */ public class ThreadLocalRandom extends Random { // CVS rev. 1.58 /* * This class implements the java.util.Random API (and subclasses * Random) using a single static instance that accesses random * number state held in class Thread (primarily, field * threadLocalRandomSeed). In doing so, it also provides a home * for managing package-private utilities that rely on exactly the * same state as needed to maintain the ThreadLocalRandom * instances. We leverage the need for an initialization flag * field to also use it as a "probe" -- a self-adjusting thread * hash used for contention avoidance, as well as a secondary * simpler (xorShift) random seed that is conservatively used to * avoid otherwise surprising users by hijacking the * ThreadLocalRandom sequence. The dual use is a marriage of * convenience, but is a simple and efficient way of reducing * application-level overhead and footprint of most concurrent * programs. Even more opportunistically, we also define here * other package-private utilities that access Thread class * fields. * * Even though this class subclasses java.util.Random, it uses the * same basic algorithm as java8.util.SplittableRandom. (See its * internal documentation for explanations, which are not repeated * here.) Because ThreadLocalRandoms are not splittable * though, we use only a single 64bit gamma. * * Because this class is in a different package than class Thread, * field access methods use Unsafe to bypass access control rules. * To conform to the requirements of the Random superclass * constructor, the common static ThreadLocalRandom maintains an * "initialized" field for the sake of rejecting user calls to * setSeed while still allowing a call from constructor. Note * that serialization is completely unnecessary because there is * only a static singleton. But we generate a serial form * containing "rnd" and "initialized" fields to ensure * compatibility across versions. * * Implementations of non-core methods are mostly the same as in * SplittableRandom, that were in part derived from a previous * version of this class. * * The nextLocalGaussian ThreadLocal supports the very rarely used * nextGaussian method by providing a holder for the second of a * pair of them. As is true for the base class version of this * method, this time/space tradeoff is probably never worthwhile, * but we provide identical statistical properties. */ /** * Field used only during singleton initialization. * True when constructor completes. */ private boolean initialized; /** Constructor used only for static singleton */ private ThreadLocalRandom() { initialized = true; // false during super() call } /** * Returns the current thread's {@code ThreadLocalRandom}. * * @return the current thread's {@code ThreadLocalRandom} */ public static ThreadLocalRandom current() { if (TLRandom.getThreadLocalRandomProbe() == 0) { TLRandom.localInit(); } return instance; } /** * Throws {@code UnsupportedOperationException}. Setting seeds in * this generator is not supported. * * @param seed not supported * * @throws UnsupportedOperationException always */ public void setSeed(long seed) { // only allow call from super() constructor if (initialized) { throw new UnsupportedOperationException(); } } private final long nextSeed() { return TLRandom.nextSeed(); } /** * The form of nextLong used by LongStream Spliterators. If * origin is greater than bound, acts as unbounded form of * nextLong, else as bounded form. * * @param origin the least value, unless greater than bound * @param bound the upper bound (exclusive), must not equal origin * @return a pseudorandom value */ private final long internalNextLong(long origin, long bound) { long r = TLRandom.mix64(nextSeed()); if (origin < bound) { long n = bound - origin, m = n - 1; if ((n & m) == 0L) // power of two r = (r & m) + origin; else if (n > 0L) { // reject over-represented candidates for (long u = r >>> 1; // ensure nonnegative u + m - (r = u % n) < 0L; // rejection check u = TLRandom.mix64(nextSeed()) >>> 1) // retry ; r += origin; } else { // range not representable as long while (r < origin || r >= bound) r = TLRandom.mix64(nextSeed()); } } return r; } /** * The form of nextInt used by IntStream Spliterators. * Exactly the same as long version, except for types. * * @param origin the least value, unless greater than bound * @param bound the upper bound (exclusive), must not equal origin * @return a pseudorandom value */ private final int internalNextInt(int origin, int bound) { int r = TLRandom.mix32(nextSeed()); if (origin < bound) { int n = bound - origin, m = n - 1; if ((n & m) == 0) r = (r & m) + origin; else if (n > 0) { for (int u = r >>> 1; u + m - (r = u % n) < 0; u = TLRandom.mix32(nextSeed()) >>> 1) ; r += origin; } else { while (r < origin || r >= bound) r = TLRandom.mix32(nextSeed()); } } return r; } /** * The form of nextDouble used by DoubleStream Spliterators. * * @param origin the least value, unless greater than bound * @param bound the upper bound (exclusive), must not equal origin * @return a pseudorandom value */ private final double internalNextDouble(double origin, double bound) { double r = (nextLong() >>> 11) * DOUBLE_UNIT; if (origin < bound) { r = r * (bound - origin) + origin; if (r >= bound) // correct for rounding r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); } return r; } /** * Returns a pseudorandom {@code int} value. * * @return a pseudorandom {@code int} value */ public int nextInt() { return TLRandom.mix32(nextSeed()); } /** * Returns a pseudorandom {@code int} value between zero (inclusive) * and the specified bound (exclusive). * * @param bound the upper bound (exclusive). Must be positive. * @return a pseudorandom {@code int} value between zero * (inclusive) and the bound (exclusive) * @throws IllegalArgumentException if {@code bound} is not positive */ public int nextInt(int bound) { if (bound <= 0) throw new IllegalArgumentException(BAD_BOUND); int r = TLRandom.mix32(nextSeed()); int m = bound - 1; if ((bound & m) == 0) // power of two r &= m; else { // reject over-represented candidates for (int u = r >>> 1; u + m - (r = u % bound) < 0; u = TLRandom.mix32(nextSeed()) >>> 1) ; } return r; } /** * Returns a pseudorandom {@code int} value between the specified * origin (inclusive) and the specified bound (exclusive). * * @param origin the least value returned * @param bound the upper bound (exclusive) * @return a pseudorandom {@code int} value between the origin * (inclusive) and the bound (exclusive) * @throws IllegalArgumentException if {@code origin} is greater than * or equal to {@code bound} */ public int nextInt(int origin, int bound) { if (origin >= bound) throw new IllegalArgumentException(BAD_RANGE); return internalNextInt(origin, bound); } /** * Returns a pseudorandom {@code long} value. * * @return a pseudorandom {@code long} value */ public long nextLong() { return TLRandom.mix64(nextSeed()); } /** * Returns a pseudorandom {@code long} value between zero (inclusive) * and the specified bound (exclusive). * * @param bound the upper bound (exclusive). Must be positive. * @return a pseudorandom {@code long} value between zero * (inclusive) and the bound (exclusive) * @throws IllegalArgumentException if {@code bound} is not positive */ public long nextLong(long bound) { if (bound <= 0) throw new IllegalArgumentException(BAD_BOUND); long r = TLRandom.mix64(nextSeed()); long m = bound - 1; if ((bound & m) == 0L) // power of two r &= m; else { // reject over-represented candidates for (long u = r >>> 1; u + m - (r = u % bound) < 0L; u = TLRandom.mix64(nextSeed()) >>> 1) ; } return r; } /** * Returns a pseudorandom {@code long} value between the specified * origin (inclusive) and the specified bound (exclusive). * * @param origin the least value returned * @param bound the upper bound (exclusive) * @return a pseudorandom {@code long} value between the origin * (inclusive) and the bound (exclusive) * @throws IllegalArgumentException if {@code origin} is greater than * or equal to {@code bound} */ public long nextLong(long origin, long bound) { if (origin >= bound) throw new IllegalArgumentException(BAD_RANGE); return internalNextLong(origin, bound); } /** * Returns a pseudorandom {@code double} value between zero * (inclusive) and one (exclusive). * * @return a pseudorandom {@code double} value between zero * (inclusive) and one (exclusive) */ public double nextDouble() { return (TLRandom.mix64(nextSeed()) >>> 11) * DOUBLE_UNIT; } /** * Returns a pseudorandom {@code double} value between 0.0 * (inclusive) and the specified bound (exclusive). * * @param bound the upper bound (exclusive). Must be positive. * @return a pseudorandom {@code double} value between zero * (inclusive) and the bound (exclusive) * @throws IllegalArgumentException if {@code bound} is not positive */ public double nextDouble(double bound) { if (!(bound > 0.0)) throw new IllegalArgumentException(BAD_BOUND); double result = (TLRandom.mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound; return (result < bound) ? result : // correct for rounding Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); } /** * Returns a pseudorandom {@code double} value between the specified * origin (inclusive) and bound (exclusive). * * @param origin the least value returned * @param bound the upper bound (exclusive) * @return a pseudorandom {@code double} value between the origin * (inclusive) and the bound (exclusive) * @throws IllegalArgumentException if {@code origin} is greater than * or equal to {@code bound} */ public double nextDouble(double origin, double bound) { if (!(origin < bound)) throw new IllegalArgumentException(BAD_RANGE); return internalNextDouble(origin, bound); } /** * Returns a pseudorandom {@code boolean} value. * * @return a pseudorandom {@code boolean} value */ public boolean nextBoolean() { return TLRandom.mix32(nextSeed()) < 0; } /** * Returns a pseudorandom {@code float} value between zero * (inclusive) and one (exclusive). * * @return a pseudorandom {@code float} value between zero * (inclusive) and one (exclusive) */ public float nextFloat() { return (TLRandom.mix32(nextSeed()) >>> 8) * FLOAT_UNIT; } /** * Returns the next pseudorandom, Gaussian ("normally") distributed * {@code double} value with mean {@code 0.0} and standard * deviation {@code 1.0} from this random number generator's sequence. *

* The general contract of {@code nextGaussian} is that one * {@code double} value, chosen from (approximately) the usual * normal distribution with mean {@code 0.0} and standard deviation * {@code 1.0}, is pseudorandomly generated and returned. * *

The method {@code nextGaussian} is implemented by class * {@code ThreadLocalRandom} as if by a thread-local version of * the following: *

 {@code
     * private double nextNextGaussian;
     * private boolean haveNextNextGaussian = false;
     *
     * public double nextGaussian() {
     *   if (haveNextNextGaussian) {
     *     haveNextNextGaussian = false;
     *     return nextNextGaussian;
     *   } else {
     *     double v1, v2, s;
     *     do {
     *       v1 = 2 * nextDouble() - 1;   // between -1.0 and 1.0
     *       v2 = 2 * nextDouble() - 1;   // between -1.0 and 1.0
     *       s = v1 * v1 + v2 * v2;
     *     } while (s >= 1 || s == 0);
     *     double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
     *     nextNextGaussian = v2 * multiplier;
     *     haveNextNextGaussian = true;
     *     return v1 * multiplier;
     *   }
     * }}
* This uses the polar method of G. E. P. Box, M. E. Muller, and * G. Marsaglia, as described by Donald E. Knuth in The Art of * Computer Programming, Volume 3: Seminumerical Algorithms, * section 3.4.1, subsection C, algorithm P. Note that it generates two * independent values at the cost of only one call to {@code StrictMath.log} * and one call to {@code StrictMath.sqrt}. * * @return the next pseudorandom, Gaussian ("normally") distributed * {@code double} value with mean {@code 0.0} and * standard deviation {@code 1.0} from this random number * generator's sequence */ public double nextGaussian() { // Use nextLocalGaussian instead of nextGaussian field Double d = nextLocalGaussian.get(); if (d != null) { nextLocalGaussian.set(null); return d.doubleValue(); } double v1, v2, s; do { v1 = 2 * nextDouble() - 1; // between -1 and 1 v2 = 2 * nextDouble() - 1; // between -1 and 1 s = v1 * v1 + v2 * v2; } while (s >= 1 || s == 0); double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s); nextLocalGaussian.set(Double.valueOf(v2 * multiplier)); return v1 * multiplier; } // stream methods, coded in a way intended to better isolate for // maintenance purposes the small differences across forms. /** * Returns a stream producing the given {@code streamSize} number of * pseudorandom {@code int} values. * * @param streamSize the number of values to generate * @return a stream of pseudorandom {@code int} values * @throws IllegalArgumentException if {@code streamSize} is * less than zero * @since 1.8 */ public IntStream ints(long streamSize) { if (streamSize < 0L) throw new IllegalArgumentException(BAD_SIZE); return StreamSupport.intStream (new RandomIntsSpliterator (0L, streamSize, Integer.MAX_VALUE, 0), false); } /** * Returns an effectively unlimited stream of pseudorandom {@code int} * values. * *

Implementation Note:
* This method is implemented to be equivalent to {@code * ints(Long.MAX_VALUE)}. * * @return a stream of pseudorandom {@code int} values * @since 1.8 */ public IntStream ints() { return StreamSupport.intStream (new RandomIntsSpliterator (0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0), false); } /** * Returns a stream producing the given {@code streamSize} number * of pseudorandom {@code int} values, each conforming to the given * origin (inclusive) and bound (exclusive). * * @param streamSize the number of values to generate * @param randomNumberOrigin the origin (inclusive) of each random value * @param randomNumberBound the bound (exclusive) of each random value * @return a stream of pseudorandom {@code int} values, * each with the given origin (inclusive) and bound (exclusive) * @throws IllegalArgumentException if {@code streamSize} is * less than zero, or {@code randomNumberOrigin} * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) { if (streamSize < 0L) throw new IllegalArgumentException(BAD_SIZE); if (randomNumberOrigin >= randomNumberBound) throw new IllegalArgumentException(BAD_RANGE); return StreamSupport.intStream (new RandomIntsSpliterator (0L, streamSize, randomNumberOrigin, randomNumberBound), false); } /** * Returns an effectively unlimited stream of pseudorandom {@code * int} values, each conforming to the given origin (inclusive) and bound * (exclusive). * *

Implementation Note:
* This method is implemented to be equivalent to {@code * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. * * @param randomNumberOrigin the origin (inclusive) of each random value * @param randomNumberBound the bound (exclusive) of each random value * @return a stream of pseudorandom {@code int} values, * each with the given origin (inclusive) and bound (exclusive) * @throws IllegalArgumentException if {@code randomNumberOrigin} * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ public IntStream ints(int randomNumberOrigin, int randomNumberBound) { if (randomNumberOrigin >= randomNumberBound) throw new IllegalArgumentException(BAD_RANGE); return StreamSupport.intStream (new RandomIntsSpliterator (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), false); } /** * Returns a stream producing the given {@code streamSize} number of * pseudorandom {@code long} values. * * @param streamSize the number of values to generate * @return a stream of pseudorandom {@code long} values * @throws IllegalArgumentException if {@code streamSize} is * less than zero * @since 1.8 */ public LongStream longs(long streamSize) { if (streamSize < 0L) throw new IllegalArgumentException(BAD_SIZE); return StreamSupport.longStream (new RandomLongsSpliterator (0L, streamSize, Long.MAX_VALUE, 0L), false); } /** * Returns an effectively unlimited stream of pseudorandom {@code long} * values. * *

Implementation Note:
* This method is implemented to be equivalent to {@code * longs(Long.MAX_VALUE)}. * * @return a stream of pseudorandom {@code long} values * @since 1.8 */ public LongStream longs() { return StreamSupport.longStream (new RandomLongsSpliterator (0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L), false); } /** * Returns a stream producing the given {@code streamSize} number of * pseudorandom {@code long}, each conforming to the given origin * (inclusive) and bound (exclusive). * * @param streamSize the number of values to generate * @param randomNumberOrigin the origin (inclusive) of each random value * @param randomNumberBound the bound (exclusive) of each random value * @return a stream of pseudorandom {@code long} values, * each with the given origin (inclusive) and bound (exclusive) * @throws IllegalArgumentException if {@code streamSize} is * less than zero, or {@code randomNumberOrigin} * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound) { if (streamSize < 0L) throw new IllegalArgumentException(BAD_SIZE); if (randomNumberOrigin >= randomNumberBound) throw new IllegalArgumentException(BAD_RANGE); return StreamSupport.longStream (new RandomLongsSpliterator (0L, streamSize, randomNumberOrigin, randomNumberBound), false); } /** * Returns an effectively unlimited stream of pseudorandom {@code * long} values, each conforming to the given origin (inclusive) and bound * (exclusive). * *

Implementation Note:
* This method is implemented to be equivalent to {@code * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. * * @param randomNumberOrigin the origin (inclusive) of each random value * @param randomNumberBound the bound (exclusive) of each random value * @return a stream of pseudorandom {@code long} values, * each with the given origin (inclusive) and bound (exclusive) * @throws IllegalArgumentException if {@code randomNumberOrigin} * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ public LongStream longs(long randomNumberOrigin, long randomNumberBound) { if (randomNumberOrigin >= randomNumberBound) throw new IllegalArgumentException(BAD_RANGE); return StreamSupport.longStream (new RandomLongsSpliterator (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), false); } /** * Returns a stream producing the given {@code streamSize} number of * pseudorandom {@code double} values, each between zero * (inclusive) and one (exclusive). * * @param streamSize the number of values to generate * @return a stream of {@code double} values * @throws IllegalArgumentException if {@code streamSize} is * less than zero * @since 1.8 */ public DoubleStream doubles(long streamSize) { if (streamSize < 0L) throw new IllegalArgumentException(BAD_SIZE); return StreamSupport.doubleStream (new RandomDoublesSpliterator (0L, streamSize, Double.MAX_VALUE, 0.0), false); } /** * Returns an effectively unlimited stream of pseudorandom {@code * double} values, each between zero (inclusive) and one * (exclusive). * *

Implementation Note:
* This method is implemented to be equivalent to {@code * doubles(Long.MAX_VALUE)}. * * @return a stream of pseudorandom {@code double} values * @since 1.8 */ public DoubleStream doubles() { return StreamSupport.doubleStream (new RandomDoublesSpliterator (0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0), false); } /** * Returns a stream producing the given {@code streamSize} number of * pseudorandom {@code double} values, each conforming to the given origin * (inclusive) and bound (exclusive). * * @param streamSize the number of values to generate * @param randomNumberOrigin the origin (inclusive) of each random value * @param randomNumberBound the bound (exclusive) of each random value * @return a stream of pseudorandom {@code double} values, * each with the given origin (inclusive) and bound (exclusive) * @throws IllegalArgumentException if {@code streamSize} is * less than zero, or {@code randomNumberOrigin} * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) { if (streamSize < 0L) throw new IllegalArgumentException(BAD_SIZE); if (!(randomNumberOrigin < randomNumberBound)) throw new IllegalArgumentException(BAD_RANGE); return StreamSupport.doubleStream (new RandomDoublesSpliterator (0L, streamSize, randomNumberOrigin, randomNumberBound), false); } /** * Returns an effectively unlimited stream of pseudorandom {@code * double} values, each conforming to the given origin (inclusive) and bound * (exclusive). * *

Implementation Note:
* This method is implemented to be equivalent to {@code * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. * * @param randomNumberOrigin the origin (inclusive) of each random value * @param randomNumberBound the bound (exclusive) of each random value * @return a stream of pseudorandom {@code double} values, * each with the given origin (inclusive) and bound (exclusive) * @throws IllegalArgumentException if {@code randomNumberOrigin} * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) { if (!(randomNumberOrigin < randomNumberBound)) throw new IllegalArgumentException(BAD_RANGE); return StreamSupport.doubleStream (new RandomDoublesSpliterator (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), false); } /** * Spliterator for int streams. We multiplex the four int * versions into one class by treating a bound less than origin as * unbounded, and also by treating "infinite" as equivalent to * Long.MAX_VALUE. For splits, it uses the standard divide-by-two * approach. The long and double versions of this class are * identical except for types. */ private static final class RandomIntsSpliterator implements Spliterator.OfInt { long index; final long fence; final int origin; final int bound; RandomIntsSpliterator(long index, long fence, int origin, int bound) { this.index = index; this.fence = fence; this.origin = origin; this.bound = bound; } public RandomIntsSpliterator trySplit() { long i = index, m = (i + fence) >>> 1; return (m <= i) ? null : new RandomIntsSpliterator(i, index = m, origin, bound); } public long estimateSize() { return fence - index; } public int characteristics() { return (Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.NONNULL | Spliterator.IMMUTABLE); } @Override public long getExactSizeIfKnown() { return Spliterators.getExactSizeIfKnown(this); } @Override public boolean hasCharacteristics(int characteristics) { return Spliterators.hasCharacteristics(this, characteristics); } @Override public Comparator getComparator() { return Spliterators.getComparator(this); } public boolean tryAdvance(IntConsumer consumer) { Objects.requireNonNull(consumer); long i = index, f = fence; if (i < f) { consumer.accept(ThreadLocalRandom.current().internalNextInt(origin, bound)); index = i + 1; return true; } return false; } @Override public boolean tryAdvance(Consumer action) { return Spliterators.OfInt.tryAdvance(this, action); } public void forEachRemaining(IntConsumer consumer) { Objects.requireNonNull(consumer); long i = index, f = fence; if (i < f) { index = f; int o = origin, b = bound; ThreadLocalRandom rng = ThreadLocalRandom.current(); do { consumer.accept(rng.internalNextInt(o, b)); } while (++i < f); } } @Override public void forEachRemaining(Consumer action) { Spliterators.OfInt.forEachRemaining(this, action); } } /** * Spliterator for long streams. */ private static final class RandomLongsSpliterator implements Spliterator.OfLong { long index; final long fence; final long origin; final long bound; RandomLongsSpliterator(long index, long fence, long origin, long bound) { this.index = index; this.fence = fence; this.origin = origin; this.bound = bound; } public RandomLongsSpliterator trySplit() { long i = index, m = (i + fence) >>> 1; return (m <= i) ? null : new RandomLongsSpliterator(i, index = m, origin, bound); } public long estimateSize() { return fence - index; } public int characteristics() { return (Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.NONNULL | Spliterator.IMMUTABLE); } @Override public long getExactSizeIfKnown() { return Spliterators.getExactSizeIfKnown(this); } @Override public boolean hasCharacteristics(int characteristics) { return Spliterators.hasCharacteristics(this, characteristics); } @Override public Comparator getComparator() { return Spliterators.getComparator(this); } public boolean tryAdvance(LongConsumer consumer) { Objects.requireNonNull(consumer); long i = index, f = fence; if (i < f) { consumer.accept(ThreadLocalRandom.current().internalNextLong(origin, bound)); index = i + 1; return true; } return false; } @Override public boolean tryAdvance(Consumer action) { return Spliterators.OfLong.tryAdvance(this, action); } public void forEachRemaining(LongConsumer consumer) { Objects.requireNonNull(consumer); long i = index, f = fence; if (i < f) { index = f; long o = origin, b = bound; ThreadLocalRandom rng = ThreadLocalRandom.current(); do { consumer.accept(rng.internalNextLong(o, b)); } while (++i < f); } } @Override public void forEachRemaining(Consumer action) { Spliterators.OfLong.forEachRemaining(this, action); } } /** * Spliterator for double streams. */ private static final class RandomDoublesSpliterator implements Spliterator.OfDouble { long index; final long fence; final double origin; final double bound; RandomDoublesSpliterator(long index, long fence, double origin, double bound) { this.index = index; this.fence = fence; this.origin = origin; this.bound = bound; } public RandomDoublesSpliterator trySplit() { long i = index, m = (i + fence) >>> 1; return (m <= i) ? null : new RandomDoublesSpliterator(i, index = m, origin, bound); } public long estimateSize() { return fence - index; } public int characteristics() { return (Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.NONNULL | Spliterator.IMMUTABLE); } @Override public long getExactSizeIfKnown() { return Spliterators.getExactSizeIfKnown(this); } @Override public boolean hasCharacteristics(int characteristics) { return Spliterators.hasCharacteristics(this, characteristics); } @Override public Comparator getComparator() { return Spliterators.getComparator(this); } public boolean tryAdvance(DoubleConsumer consumer) { Objects.requireNonNull(consumer); long i = index, f = fence; if (i < f) { consumer.accept(ThreadLocalRandom.current().internalNextDouble(origin, bound)); index = i + 1; return true; } return false; } @Override public boolean tryAdvance(Consumer action) { return Spliterators.OfDouble.tryAdvance(this, action); } public void forEachRemaining(DoubleConsumer consumer) { Objects.requireNonNull(consumer); long i = index, f = fence; if (i < f) { index = f; double o = origin, b = bound; ThreadLocalRandom rng = ThreadLocalRandom.current(); do { consumer.accept(rng.internalNextDouble(o, b)); } while (++i < f); } } @Override public void forEachRemaining(Consumer action) { Spliterators.OfDouble.forEachRemaining(this, action); } } // Serialization support private static final long serialVersionUID = 9123313859120073139L; /** * @serialField rnd long * seed for random computations * @serialField initialized boolean * always true */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("rnd", long.class), new ObjectStreamField("initialized", boolean.class), }; /** * Saves the {@code ThreadLocalRandom} to a stream (that is, serializes it). * @param s the stream * @throws java.io.IOException if an I/O error occurs */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { java.io.ObjectOutputStream.PutField fields = s.putFields(); fields.put("rnd", TLRandom.getThreadLocalRandomSeed()); fields.put("initialized", true); s.writeFields(); } /** * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}. * @return the {@link #current() current} thread's {@code ThreadLocalRandom} */ private Object readResolve() { return current(); } // Static initialization /** * The least non-zero value returned by nextDouble(). This value * is scaled by a random value of 53 bits to produce a result. */ private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53) private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24) // IllegalArgumentException messages private static final String BAD_BOUND = "bound must be positive"; private static final String BAD_RANGE = "bound must be greater than origin"; private static final String BAD_SIZE = "size must be non-negative"; /** Rarely-used holder for the second of a pair of Gaussians */ private static final ThreadLocal nextLocalGaussian = new ThreadLocal<>(); /** The common ThreadLocalRandom */ private static final ThreadLocalRandom instance = new ThreadLocalRandom(); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy