--- jsr166/src/jsr166y/ThreadLocalRandom.java 2009/01/12 17:16:18 1.1 +++ jsr166/src/jsr166y/ThreadLocalRandom.java 2009/07/31 16:25:20 1.11 @@ -5,20 +5,31 @@ */ package jsr166y; -import java.util.*; + +import java.util.Random; /** - * A Random number generator with the same properties as {@link - * Random} but isolated to the current Thread. Like the global - * generator used by {@link java.lang.Math}, a ThreadLocalRandom is - * initialized with an internally generated seed that may not - * otherwise be modified. When applicable, use of ThreadLocalRandom - * rather than shared Random objects in concurrent programs will - * typically encounter less overhead and contention. The most common - * usage form is: ThreadLocalRandom.current().nextX(). + * 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 ThreadLocalRandom is initialized with an + * internally generated seed that may not otherwise be modified. When + * applicable, use of ThreadLocalRandom rather than shared Random + * objects in concurrent programs will typically encounter much less + * overhead and contention. ThreadLocalRandoms are 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 + * accidently share ThreadLocalRandoms across multiple threads. * *

This class also provides additional commonly used bounded random * generation methods. + * + * @since 1.7 + * @author Doug Lea */ public class ThreadLocalRandom extends Random { // same constants as Random, but must be redeclared because private @@ -27,15 +38,15 @@ public class ThreadLocalRandom extends R private final static long mask = (1L << 48) - 1; /** - * The random seed. We can't use super.seed + * The random seed. We can't use super.seed. */ - private long rnd; + private long rnd; /** * Initialization flag to permit the first and only allowed call * to setSeed (inside Random constructor) to succeed. We can't * allow others since it would cause setting seed in one part of a - * program to inintentionally impact other usages by the thread. + * program to unintentionally impact other usages by the thread. */ boolean initialized; @@ -44,6 +55,9 @@ public class ThreadLocalRandom extends R // each other. private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; + /** + * The actual ThreadLocal + */ private static final ThreadLocal localRandom = new ThreadLocal() { protected ThreadLocalRandom initialValue() { @@ -51,12 +65,19 @@ public class ThreadLocalRandom extends R } }; - ThreadLocalRandom() { // construct only in localRandom.initialValue - super(); // super constructor calls setSeed + + /** + * Constructor called only by localRandom.initialValue. + * We rely on the fact that the superclass no-arg constructor + * invokes setSeed exactly once to initialize. + */ + ThreadLocalRandom() { + super(); } /** - * Returns the current Thread's ThreadLocalRandom + * Returns the current Thread's ThreadLocalRandom. + * * @return the current Thread's ThreadLocalRandom */ public static ThreadLocalRandom current() { @@ -66,9 +87,10 @@ public class ThreadLocalRandom extends R /** * Throws UnsupportedOperationException. Setting seeds in this * generator is unsupported. - * @throw UnsupportedOperationException always + * + * @throws UnsupportedOperationException always */ - public void setSeed(long seed) { + public void setSeed(long seed) { if (initialized) throw new UnsupportedOperationException(); initialized = true; @@ -76,12 +98,14 @@ public class ThreadLocalRandom extends R } protected int next(int bits) { - return (int)((rnd = (rnd * multiplier + addend) & mask) >>> (48-bits)); + rnd = (rnd * multiplier + addend) & mask; + return (int) (rnd >>> (48-bits)); } /** * Returns a pseudorandom, uniformly distributed value between the * given least value (inclusive) and bound (exclusive). + * * @param least the least value returned * @param bound the upper bound (exclusive) * @throws IllegalArgumentException if least greater than or equal @@ -96,7 +120,8 @@ public class ThreadLocalRandom extends R /** * Returns a pseudorandom, uniformly distributed value - * between 0 (inclusive) and the specified value (exclusive) + * between 0 (inclusive) and the specified value (exclusive). + * * @param n the bound on the random number to be returned. Must be * positive. * @return the next value @@ -105,21 +130,27 @@ public class ThreadLocalRandom extends R public long nextLong(long n) { if (n <= 0) throw new IllegalArgumentException("n must be positive"); + // Divide n by two until small enough for nextInt. On each + // iteration (at most 31 of them but usually much less), + // randomly choose both whether to include high bit in result + // (offset) and whether to continue with the lower vs upper + // half (which makes a difference only if odd). long offset = 0; - while (n >= Integer.MAX_VALUE) { // randomly pick half range - int bits = next(2); // 2nd bit for odd vs even split + while (n >= Integer.MAX_VALUE) { + int bits = next(2); long half = n >>> 1; - long nextn = ((bits & 2) == 0)? half : n - half; + long nextn = ((bits & 2) == 0) ? half : n - half; if ((bits & 1) == 0) offset += n - nextn; n = nextn; } - return offset + nextInt((int)n); + return offset + nextInt((int) n); } /** * Returns a pseudorandom, uniformly distributed value between the * given least value (inclusive) and bound (exclusive). + * * @param least the least value returned * @param bound the upper bound (exclusive) * @return the next value @@ -134,7 +165,8 @@ public class ThreadLocalRandom extends R /** * Returns a pseudorandom, uniformly distributed {@code double} value - * between 0 (inclusive) and the specified value (exclusive) + * between 0 (inclusive) and the specified value (exclusive). + * * @param n the bound on the random number to be returned. Must be * positive. * @return the next value @@ -149,6 +181,7 @@ public class ThreadLocalRandom extends R /** * Returns a pseudorandom, uniformly distributed value between the * given least value (inclusive) and bound (exclusive). + * * @param least the least value returned * @param bound the upper bound (exclusive) * @return the next value @@ -161,4 +194,5 @@ public class ThreadLocalRandom extends R return nextDouble() * (bound - least) + least; } -} \ No newline at end of file + private static final long serialVersionUID = -5851777807851030925L; +}