Home | History | Annotate | Download | only in concurrent
      1 /*
      2  * Written by Doug Lea with assistance from members of JCP JSR-166
      3  * Expert Group and released to the public domain, as explained at
      4  * http://creativecommons.org/publicdomain/zero/1.0/
      5  */
      6 
      7 package java.util.concurrent;
      8 
      9 import java.util.Random;
     10 
     11 /**
     12  * A random number generator isolated to the current thread.  Like the
     13  * global {@link java.util.Random} generator used by the {@link
     14  * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
     15  * with an internally generated seed that may not otherwise be
     16  * modified. When applicable, use of {@code ThreadLocalRandom} rather
     17  * than shared {@code Random} objects in concurrent programs will
     18  * typically encounter much less overhead and contention.  Use of
     19  * {@code ThreadLocalRandom} is particularly appropriate when multiple
     20  * tasks (for example, each a {@link ForkJoinTask}) use random numbers
     21  * in parallel in thread pools.
     22  *
     23  * <p>Usages of this class should typically be of the form:
     24  * {@code ThreadLocalRandom.current().nextX(...)} (where
     25  * {@code X} is {@code Int}, {@code Long}, etc).
     26  * When all usages are of this form, it is never possible to
     27  * accidently share a {@code ThreadLocalRandom} across multiple threads.
     28  *
     29  * <p>This class also provides additional commonly used bounded random
     30  * generation methods.
     31  *
     32  * @since 1.7
     33  * @author Doug Lea
     34  */
     35 public class ThreadLocalRandom extends Random {
     36     // same constants as Random, but must be redeclared because private
     37     private static final long multiplier = 0x5DEECE66DL;
     38     private static final long addend = 0xBL;
     39     private static final long mask = (1L << 48) - 1;
     40 
     41     /**
     42      * The random seed. We can't use super.seed.
     43      */
     44     private long rnd;
     45 
     46     /**
     47      * Initialization flag to permit calls to setSeed to succeed only
     48      * while executing the Random constructor.  We can't allow others
     49      * since it would cause setting seed in one part of a program to
     50      * unintentionally impact other usages by the thread.
     51      */
     52     boolean initialized;
     53 
     54     // Padding to help avoid memory contention among seed updates in
     55     // different TLRs in the common case that they are located near
     56     // each other.
     57     private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
     58 
     59     /**
     60      * The actual ThreadLocal
     61      */
     62     private static final ThreadLocal<ThreadLocalRandom> localRandom =
     63         new ThreadLocal<ThreadLocalRandom>() {
     64             protected ThreadLocalRandom initialValue() {
     65                 return new ThreadLocalRandom();
     66             }
     67     };
     68 
     69 
     70     /**
     71      * Constructor called only by localRandom.initialValue.
     72      */
     73     ThreadLocalRandom() {
     74         super();
     75         initialized = true;
     76     }
     77 
     78     /**
     79      * Returns the current thread's {@code ThreadLocalRandom}.
     80      *
     81      * @return the current thread's {@code ThreadLocalRandom}
     82      */
     83     public static ThreadLocalRandom current() {
     84         return localRandom.get();
     85     }
     86 
     87     /**
     88      * Throws {@code UnsupportedOperationException}.  Setting seeds in
     89      * this generator is not supported.
     90      *
     91      * @throws UnsupportedOperationException always
     92      */
     93     public void setSeed(long seed) {
     94         if (initialized)
     95             throw new UnsupportedOperationException();
     96         rnd = (seed ^ multiplier) & mask;
     97     }
     98 
     99     protected int next(int bits) {
    100         rnd = (rnd * multiplier + addend) & mask;
    101         return (int) (rnd >>> (48-bits));
    102     }
    103 
    104     /**
    105      * Returns a pseudorandom, uniformly distributed value between the
    106      * given least value (inclusive) and bound (exclusive).
    107      *
    108      * @param least the least value returned
    109      * @param bound the upper bound (exclusive)
    110      * @throws IllegalArgumentException if least greater than or equal
    111      * to bound
    112      * @return the next value
    113      */
    114     public int nextInt(int least, int bound) {
    115         if (least >= bound)
    116             throw new IllegalArgumentException();
    117         return nextInt(bound - least) + least;
    118     }
    119 
    120     /**
    121      * Returns a pseudorandom, uniformly distributed value
    122      * between 0 (inclusive) and the specified value (exclusive).
    123      *
    124      * @param n the bound on the random number to be returned.  Must be
    125      *        positive.
    126      * @return the next value
    127      * @throws IllegalArgumentException if n is not positive
    128      */
    129     public long nextLong(long n) {
    130         if (n <= 0)
    131             throw new IllegalArgumentException("n must be positive");
    132         // Divide n by two until small enough for nextInt. On each
    133         // iteration (at most 31 of them but usually much less),
    134         // randomly choose both whether to include high bit in result
    135         // (offset) and whether to continue with the lower vs upper
    136         // half (which makes a difference only if odd).
    137         long offset = 0;
    138         while (n >= Integer.MAX_VALUE) {
    139             int bits = next(2);
    140             long half = n >>> 1;
    141             long nextn = ((bits & 2) == 0) ? half : n - half;
    142             if ((bits & 1) == 0)
    143                 offset += n - nextn;
    144             n = nextn;
    145         }
    146         return offset + nextInt((int) n);
    147     }
    148 
    149     /**
    150      * Returns a pseudorandom, uniformly distributed value between the
    151      * given least value (inclusive) and bound (exclusive).
    152      *
    153      * @param least the least value returned
    154      * @param bound the upper bound (exclusive)
    155      * @return the next value
    156      * @throws IllegalArgumentException if least greater than or equal
    157      * to bound
    158      */
    159     public long nextLong(long least, long bound) {
    160         if (least >= bound)
    161             throw new IllegalArgumentException();
    162         return nextLong(bound - least) + least;
    163     }
    164 
    165     /**
    166      * Returns a pseudorandom, uniformly distributed {@code double} value
    167      * between 0 (inclusive) and the specified value (exclusive).
    168      *
    169      * @param n the bound on the random number to be returned.  Must be
    170      *        positive.
    171      * @return the next value
    172      * @throws IllegalArgumentException if n is not positive
    173      */
    174     public double nextDouble(double n) {
    175         if (n <= 0)
    176             throw new IllegalArgumentException("n must be positive");
    177         return nextDouble() * n;
    178     }
    179 
    180     /**
    181      * Returns a pseudorandom, uniformly distributed value between the
    182      * given least value (inclusive) and bound (exclusive).
    183      *
    184      * @param least the least value returned
    185      * @param bound the upper bound (exclusive)
    186      * @return the next value
    187      * @throws IllegalArgumentException if least greater than or equal
    188      * to bound
    189      */
    190     public double nextDouble(double least, double bound) {
    191         if (least >= bound)
    192             throw new IllegalArgumentException();
    193         return nextDouble() * (bound - least) + least;
    194     }
    195 
    196     private static final long serialVersionUID = -5851777807851030925L;
    197 }
    198