ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166y/ThreadLocalRandom.java
Revision: 1.1
Committed: Mon Jan 12 17:16:18 2009 UTC (15 years, 4 months ago) by dl
Branch: MAIN
Log Message:
Split out ThreadLocalRandom; internal refactoring pass

File Contents

# Content
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/licenses/publicdomain
5 */
6
7 package jsr166y;
8 import java.util.*;
9
10 /**
11 * A Random number generator with the same properties as {@link
12 * Random} but isolated to the current Thread. Like the global
13 * generator used by {@link java.lang.Math}, a ThreadLocalRandom is
14 * initialized with an internally generated seed that may not
15 * otherwise be modified. When applicable, use of ThreadLocalRandom
16 * rather than shared Random objects in concurrent programs will
17 * typically encounter less overhead and contention. The most common
18 * usage form is: <code>ThreadLocalRandom.current().nextX()</code>.
19 *
20 * <p>This class also provides additional commonly used bounded random
21 * generation methods.
22 */
23 public class ThreadLocalRandom extends Random {
24 // same constants as Random, but must be redeclared because private
25 private final static long multiplier = 0x5DEECE66DL;
26 private final static long addend = 0xBL;
27 private final static long mask = (1L << 48) - 1;
28
29 /**
30 * The random seed. We can't use super.seed
31 */
32 private long rnd;
33
34 /**
35 * Initialization flag to permit the first and only allowed call
36 * to setSeed (inside Random constructor) to succeed. We can't
37 * allow others since it would cause setting seed in one part of a
38 * program to inintentionally impact other usages by the thread.
39 */
40 boolean initialized;
41
42 // Padding to help avoid memory contention among seed updates in
43 // different TLRs in the common case that they are located near
44 // each other.
45 private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
46
47 private static final ThreadLocal<ThreadLocalRandom> localRandom =
48 new ThreadLocal<ThreadLocalRandom>() {
49 protected ThreadLocalRandom initialValue() {
50 return new ThreadLocalRandom();
51 }
52 };
53
54 ThreadLocalRandom() { // construct only in localRandom.initialValue
55 super(); // super constructor calls setSeed
56 }
57
58 /**
59 * Returns the current Thread's ThreadLocalRandom
60 * @return the current Thread's ThreadLocalRandom
61 */
62 public static ThreadLocalRandom current() {
63 return localRandom.get();
64 }
65
66 /**
67 * Throws UnsupportedOperationException. Setting seeds in this
68 * generator is unsupported.
69 * @throw UnsupportedOperationException always
70 */
71 public void setSeed(long seed) {
72 if (initialized)
73 throw new UnsupportedOperationException();
74 initialized = true;
75 rnd = (seed ^ multiplier) & mask;
76 }
77
78 protected int next(int bits) {
79 return (int)((rnd = (rnd * multiplier + addend) & mask) >>> (48-bits));
80 }
81
82 /**
83 * Returns a pseudorandom, uniformly distributed value between the
84 * given least value (inclusive) and bound (exclusive).
85 * @param least the least value returned
86 * @param bound the upper bound (exclusive)
87 * @throws IllegalArgumentException if least greater than or equal
88 * to bound
89 * @return the next value
90 */
91 public int nextInt(int least, int bound) {
92 if (least >= bound)
93 throw new IllegalArgumentException();
94 return nextInt(bound - least) + least;
95 }
96
97 /**
98 * Returns a pseudorandom, uniformly distributed value
99 * between 0 (inclusive) and the specified value (exclusive)
100 * @param n the bound on the random number to be returned. Must be
101 * positive.
102 * @return the next value
103 * @throws IllegalArgumentException if n is not positive
104 */
105 public long nextLong(long n) {
106 if (n <= 0)
107 throw new IllegalArgumentException("n must be positive");
108 long offset = 0;
109 while (n >= Integer.MAX_VALUE) { // randomly pick half range
110 int bits = next(2); // 2nd bit for odd vs even split
111 long half = n >>> 1;
112 long nextn = ((bits & 2) == 0)? half : n - half;
113 if ((bits & 1) == 0)
114 offset += n - nextn;
115 n = nextn;
116 }
117 return offset + nextInt((int)n);
118 }
119
120 /**
121 * Returns a pseudorandom, uniformly distributed value between the
122 * given least value (inclusive) and bound (exclusive).
123 * @param least the least value returned
124 * @param bound the upper bound (exclusive)
125 * @return the next value
126 * @throws IllegalArgumentException if least greater than or equal
127 * to bound
128 */
129 public long nextLong(long least, long bound) {
130 if (least >= bound)
131 throw new IllegalArgumentException();
132 return nextLong(bound - least) + least;
133 }
134
135 /**
136 * Returns a pseudorandom, uniformly distributed {@code double} value
137 * between 0 (inclusive) and the specified value (exclusive)
138 * @param n the bound on the random number to be returned. Must be
139 * positive.
140 * @return the next value
141 * @throws IllegalArgumentException if n is not positive
142 */
143 public double nextDouble(double n) {
144 if (n <= 0)
145 throw new IllegalArgumentException("n must be positive");
146 return nextDouble() * n;
147 }
148
149 /**
150 * Returns a pseudorandom, uniformly distributed value between the
151 * given least value (inclusive) and bound (exclusive).
152 * @param least the least value returned
153 * @param bound the upper bound (exclusive)
154 * @return the next value
155 * @throws IllegalArgumentException if least greater than or equal
156 * to bound
157 */
158 public double nextDouble(double least, double bound) {
159 if (least >= bound)
160 throw new IllegalArgumentException();
161 return nextDouble() * (bound - least) + least;
162 }
163
164 }