ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ThreadLocalRandom.java
Revision: 1.64
Committed: Fri Mar 18 16:01:42 2022 UTC (2 years, 2 months ago) by dl
Branch: MAIN
Changes since 1.63: +320 -747 lines
Log Message:
jdk17+ suppressWarnings, FJ updates

File Contents

# User Rev Content
1 jsr166 1.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 jsr166 1.6 * http://creativecommons.org/publicdomain/zero/1.0/
5 dl 1.64 * Additional modifications by Guy Steele in 2019 to refactor the code
6     * and to implement the {@link RandomGenerator} interface.
7 jsr166 1.1 */
8    
9     package java.util.concurrent;
10    
11 dl 1.25 import java.io.ObjectStreamField;
12 dl 1.64 import java.math.BigInteger;
13 dl 1.44 import java.security.AccessControlContext;
14 dl 1.64 import java.util.Map;
15 jsr166 1.1 import java.util.Random;
16 dl 1.19 import java.util.Spliterator;
17 dl 1.7 import java.util.concurrent.atomic.AtomicInteger;
18     import java.util.concurrent.atomic.AtomicLong;
19 dl 1.64 import java.util.random.RandomGenerator;
20 dl 1.19 import java.util.stream.DoubleStream;
21     import java.util.stream.IntStream;
22     import java.util.stream.LongStream;
23 dl 1.64 import jdk.internal.util.random.RandomSupport;
24     import jdk.internal.util.random.RandomSupport.*;
25 jsr166 1.46 import jdk.internal.misc.Unsafe;
26 dl 1.54 import jdk.internal.misc.VM;
27 jsr166 1.1
28     /**
29 dl 1.64 * A random number generator (with period 2<sup>64</sup>) isolated
30     * to the current thread. Like the global {@link java.util.Random}
31     * generator used by the {@link java.lang.Math} class,
32     * a {@code ThreadLocalRandom} is initialized
33 jsr166 1.3 * with an internally generated seed that may not otherwise be
34     * modified. When applicable, use of {@code ThreadLocalRandom} rather
35     * than shared {@code Random} objects in concurrent programs will
36     * typically encounter much less overhead and contention. Use of
37     * {@code ThreadLocalRandom} is particularly appropriate when multiple
38     * tasks (for example, each a {@link ForkJoinTask}) use random numbers
39     * in parallel in thread pools.
40 jsr166 1.1 *
41     * <p>Usages of this class should typically be of the form:
42     * {@code ThreadLocalRandom.current().nextX(...)} (where
43     * {@code X} is {@code Int}, {@code Long}, etc).
44     * When all usages are of this form, it is never possible to
45 jsr166 1.57 * accidentally share a {@code ThreadLocalRandom} across multiple threads.
46 jsr166 1.1 *
47     * <p>This class also provides additional commonly used bounded random
48     * generation methods.
49     *
50 dl 1.21 * <p>Instances of {@code ThreadLocalRandom} are not cryptographically
51     * secure. Consider instead using {@link java.security.SecureRandom}
52 dl 1.23 * in security-sensitive applications. Additionally,
53     * default-constructed instances do not use a cryptographically random
54     * seed unless the {@linkplain System#getProperty system property}
55 jsr166 1.60 * {@code java.util.secureRandomSeed} is set to {@code true}.
56 dl 1.21 *
57 jsr166 1.1 * @since 1.7
58     * @author Doug Lea
59     */
60 dl 1.64
61     @RandomGeneratorProperties(
62     name = "ThreadLocalRandom",
63     i = 64, j = 0, k = 0,
64     equidistribution = 1
65     )
66 jsr166 1.1 public class ThreadLocalRandom extends Random {
67 dl 1.7 /*
68     * This class implements the java.util.Random API (and subclasses
69 dl 1.64 * Random) using a single static instance that accesses 64 bits of
70     * random number state held in class java.lang.Thread (field
71 dl 1.7 * threadLocalRandomSeed). In doing so, it also provides a home
72     * for managing package-private utilities that rely on exactly the
73     * same state as needed to maintain the ThreadLocalRandom
74     * instances. We leverage the need for an initialization flag
75     * field to also use it as a "probe" -- a self-adjusting thread
76     * hash used for contention avoidance, as well as a secondary
77     * simpler (xorShift) random seed that is conservatively used to
78     * avoid otherwise surprising users by hijacking the
79     * ThreadLocalRandom sequence. The dual use is a marriage of
80     * convenience, but is a simple and efficient way of reducing
81     * application-level overhead and footprint of most concurrent
82 dl 1.44 * programs. Even more opportunistically, we also define here
83     * other package-private utilities that access Thread class
84     * fields.
85 dl 1.7 *
86 dl 1.19 * Even though this class subclasses java.util.Random, it uses the
87     * same basic algorithm as java.util.SplittableRandom. (See its
88     * internal documentation for explanations, which are not repeated
89 dl 1.64 * here.) Note that ThreadLocalRandom is not a "splittable" generator
90     * (it does not support the split method), but it behaves as if
91     * one instance of the SplittableRandom algorithm had been
92     * created for each thread, each with a distinct gamma parameter
93     * (calculated from the thread id).
94 dl 1.19 *
95 dl 1.7 * Because this class is in a different package than class Thread,
96 jsr166 1.15 * field access methods use Unsafe to bypass access control rules.
97 dl 1.19 * To conform to the requirements of the Random superclass
98     * constructor, the common static ThreadLocalRandom maintains an
99     * "initialized" field for the sake of rejecting user calls to
100     * setSeed while still allowing a call from constructor. Note
101     * that serialization is completely unnecessary because there is
102     * only a static singleton. But we generate a serial form
103     * containing "rnd" and "initialized" fields to ensure
104     * compatibility across versions.
105     *
106     * Implementations of non-core methods are mostly the same as in
107     * SplittableRandom, that were in part derived from a previous
108     * version of this class.
109 dl 1.7 *
110 dl 1.64 * This implementation of ThreadLocalRandom overrides the
111     * definition of the nextGaussian() method in the class Random,
112     * and instead uses the ziggurat-based algorithm that is the
113     * default for the RandomGenerator interface.
114 dl 1.7 */
115    
116 dl 1.19 private static int mix32(long z) {
117     z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
118     return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
119     }
120    
121 jsr166 1.11 /**
122     * Field used only during singleton initialization.
123     * True when constructor completes.
124 jsr166 1.1 */
125 jsr166 1.11 boolean initialized;
126 dl 1.7
127     /** Constructor used only for static singleton */
128     private ThreadLocalRandom() {
129     initialized = true; // false during super() call
130     }
131 jsr166 1.1
132     /**
133 dl 1.7 * Initialize Thread fields for the current thread. Called only
134     * when Thread.threadLocalRandomProbe is zero, indicating that a
135     * thread local seed value needs to be generated. Note that even
136     * though the initialization is purely thread-local, we need to
137     * rely on (static) atomic generators to initialize the values.
138     */
139     static final void localInit() {
140 dl 1.19 int p = probeGenerator.addAndGet(PROBE_INCREMENT);
141 dl 1.7 int probe = (p == 0) ? 1 : p; // skip 0
142 dl 1.64 long seed = RandomSupport.mixMurmur64(seeder.getAndAdd(SEEDER_INCREMENT));
143 dl 1.7 Thread t = Thread.currentThread();
144 jsr166 1.33 U.putLong(t, SEED, seed);
145     U.putInt(t, PROBE, probe);
146 jsr166 1.1 }
147    
148     /**
149 dl 1.64 * Returns the current thread's {@code ThreadLocalRandom} object.
150     * Methods of this object should be called only by the current thread,
151     * not by other threads.
152 jsr166 1.1 *
153 jsr166 1.3 * @return the current thread's {@code ThreadLocalRandom}
154 jsr166 1.1 */
155     public static ThreadLocalRandom current() {
156 jsr166 1.33 if (U.getInt(Thread.currentThread(), PROBE) == 0)
157 dl 1.7 localInit();
158     return instance;
159 jsr166 1.1 }
160    
161     /**
162 jsr166 1.3 * Throws {@code UnsupportedOperationException}. Setting seeds in
163     * this generator is not supported.
164 jsr166 1.1 *
165     * @throws UnsupportedOperationException always
166     */
167     public void setSeed(long seed) {
168 jsr166 1.15 // only allow call from super() constructor
169     if (initialized)
170 jsr166 1.1 throw new UnsupportedOperationException();
171     }
172    
173 dl 1.64 /**
174     * Update the thread local seed value by adding to it the sum
175     * of {@code GOLDEN_GAMMA} (an odd value) and twice the thread id.
176     * This sum is always odd (to guarantee that the generator
177     * has maximum period) and is different for different threads.
178     * Because thread id values are allocated consecutively starting
179     * from 0, the high 32 bits of this sum will be the same as the
180     * high 32 bits of {@code GOLDEN_GAMMA} unless an extremely large
181     * number of threads have been created, and so the overall
182     * value added to the thread local seed value will have at least
183     * fourteen 01 and 10 transitions (see the documentation for the
184     * method {@code mixGamma} in class {@code SplittableRandom}),
185     * which should provide adequate statistical quality for
186     * applications likely to use {@code ThreadLocalRandom}.
187     */
188 dl 1.19 final long nextSeed() {
189     Thread t; long r; // read and update per-thread seed
190 jsr166 1.33 U.putLong(t = Thread.currentThread(), SEED,
191 dl 1.64 r = U.getLong(t, SEED) + (t.getId() << 1) + GOLDEN_GAMMA);
192 dl 1.19 return r;
193     }
194    
195 dl 1.47 /**
196     * Generates a pseudorandom number with the indicated number of
197 jsr166 1.49 * low-order bits. Because this class has no subclasses, this
198 jsr166 1.50 * method cannot be invoked or overridden.
199 dl 1.47 *
200     * @param bits random bits
201     * @return the next pseudorandom value from this random number
202     * generator's sequence
203     */
204 jsr166 1.1 protected int next(int bits) {
205 jsr166 1.49 return nextInt() >>> (32 - bits);
206 dl 1.19 }
207    
208 dl 1.7 // Within-package utilities
209    
210     /*
211     * Descriptions of the usages of the methods below can be found in
212     * the classes that use them. Briefly, a thread's "probe" value is
213     * a non-zero hash code that (probably) does not collide with
214     * other existing threads with respect to any power of two
215     * collision space. When it does collide, it is pseudo-randomly
216     * adjusted (using a Marsaglia XorShift). The nextSecondarySeed
217     * method is used in the same contexts as ThreadLocalRandom, but
218     * only for transient usages such as random adaptive spin/block
219     * sequences for which a cheap RNG suffices and for which it could
220     * in principle disrupt user-visible statistical properties of the
221     * main ThreadLocalRandom if we were to use it.
222     *
223     * Note: Because of package-protection issues, versions of some
224 dl 1.9 * these methods also appear in some subpackage classes.
225 dl 1.7 */
226    
227     /**
228     * Returns the probe value for the current thread without forcing
229     * initialization. Note that invoking ThreadLocalRandom.current()
230     * can be used to force initialization on zero return.
231     */
232     static final int getProbe() {
233 jsr166 1.33 return U.getInt(Thread.currentThread(), PROBE);
234 dl 1.7 }
235    
236     /**
237     * Pseudo-randomly advances and records the given probe value for the
238     * given thread.
239     */
240     static final int advanceProbe(int probe) {
241     probe ^= probe << 13; // xorshift
242     probe ^= probe >>> 17;
243     probe ^= probe << 5;
244 jsr166 1.33 U.putInt(Thread.currentThread(), PROBE, probe);
245 dl 1.7 return probe;
246     }
247    
248     /**
249     * Returns the pseudo-randomly initialized or updated secondary seed.
250     */
251     static final int nextSecondarySeed() {
252     int r;
253     Thread t = Thread.currentThread();
254 jsr166 1.33 if ((r = U.getInt(t, SECONDARY)) != 0) {
255 dl 1.7 r ^= r << 13; // xorshift
256     r ^= r >>> 17;
257     r ^= r << 5;
258     }
259 dl 1.28 else if ((r = mix32(seeder.getAndAdd(SEEDER_INCREMENT))) == 0)
260 jsr166 1.29 r = 1; // avoid zero
261 jsr166 1.33 U.putInt(t, SECONDARY, r);
262 dl 1.7 return r;
263     }
264    
265 dl 1.44 // Support for other package-private ThreadLocal access
266    
267     /**
268     * Erases ThreadLocals by nulling out Thread maps.
269     */
270     static final void eraseThreadLocals(Thread thread) {
271 dl 1.64 U.putReference(thread, THREADLOCALS, null);
272     U.putReference(thread, INHERITABLETHREADLOCALS, null);
273 jsr166 1.45 }
274 dl 1.44
275     static final void setInheritedAccessControlContext(Thread thread,
276 dl 1.64 @SuppressWarnings("removal") AccessControlContext acc) {
277     U.putReferenceRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
278 dl 1.44 }
279    
280 jsr166 1.13 // Serialization support
281 dl 1.9
282 jsr166 1.1 private static final long serialVersionUID = -5851777807851030925L;
283 dl 1.7
284 dl 1.9 /**
285 jsr166 1.14 * @serialField rnd long
286     * seed for random computations
287     * @serialField initialized boolean
288     * always true
289     */
290     private static final ObjectStreamField[] serialPersistentFields = {
291 jsr166 1.31 new ObjectStreamField("rnd", long.class),
292     new ObjectStreamField("initialized", boolean.class),
293 jsr166 1.14 };
294    
295     /**
296     * Saves the {@code ThreadLocalRandom} to a stream (that is, serializes it).
297 jsr166 1.16 * @param s the stream
298 jsr166 1.17 * @throws java.io.IOException if an I/O error occurs
299 jsr166 1.14 */
300 jsr166 1.16 private void writeObject(java.io.ObjectOutputStream s)
301 jsr166 1.14 throws java.io.IOException {
302    
303 jsr166 1.16 java.io.ObjectOutputStream.PutField fields = s.putFields();
304 jsr166 1.33 fields.put("rnd", U.getLong(Thread.currentThread(), SEED));
305 jsr166 1.14 fields.put("initialized", true);
306 jsr166 1.16 s.writeFields();
307 jsr166 1.14 }
308    
309     /**
310 dl 1.9 * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}.
311 jsr166 1.16 * @return the {@link #current() current} thread's {@code ThreadLocalRandom}
312 dl 1.9 */
313     private Object readResolve() {
314     return current();
315     }
316    
317 jsr166 1.41 // Static initialization
318    
319     /**
320 dl 1.64 * The seed increment. This must be an odd value for the generator to
321     * have the maximum period (2 to the 64th power).
322     *
323     * The value 0x9e3779b97f4a7c15L is odd, and moreover consists of the
324     * first 64 bits of the fractional part of the golden ratio,
325     * which is known to generate good Weyl sequences.
326 jsr166 1.41 */
327 dl 1.64 private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L;
328 jsr166 1.41
329     /**
330     * The increment for generating probe values.
331     */
332     private static final int PROBE_INCREMENT = 0x9e3779b9;
333    
334     /**
335     * The increment of seeder per new instance.
336     */
337     private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
338    
339     // IllegalArgumentException messages
340     static final String BAD_BOUND = "bound must be positive";
341     static final String BAD_RANGE = "bound must be greater than origin";
342     static final String BAD_SIZE = "size must be non-negative";
343    
344 dl 1.7 // Unsafe mechanics
345 jsr166 1.46 private static final Unsafe U = Unsafe.getUnsafe();
346 jsr166 1.63 private static final long SEED
347     = U.objectFieldOffset(Thread.class, "threadLocalRandomSeed");
348     private static final long PROBE
349     = U.objectFieldOffset(Thread.class, "threadLocalRandomProbe");
350     private static final long SECONDARY
351     = U.objectFieldOffset(Thread.class, "threadLocalRandomSecondarySeed");
352     private static final long THREADLOCALS
353     = U.objectFieldOffset(Thread.class, "threadLocals");
354     private static final long INHERITABLETHREADLOCALS
355     = U.objectFieldOffset(Thread.class, "inheritableThreadLocals");
356     private static final long INHERITEDACCESSCONTROLCONTEXT
357     = U.objectFieldOffset(Thread.class, "inheritedAccessControlContext");
358 jsr166 1.41
359     /** Generates per-thread initialization/probe field */
360     private static final AtomicInteger probeGenerator = new AtomicInteger();
361    
362     /** The common ThreadLocalRandom */
363 dl 1.64 private static final ThreadLocalRandom instance = new ThreadLocalRandom();
364 jsr166 1.41
365     /**
366     * The next seed for default constructors.
367     */
368     private static final AtomicLong seeder
369 dl 1.64 = new AtomicLong(RandomSupport.mixMurmur64(System.currentTimeMillis()) ^
370     RandomSupport.mixMurmur64(System.nanoTime()));
371 jsr166 1.41
372     // at end of <clinit> to survive static initialization circularity
373     static {
374 dl 1.54 String sec = VM.getSavedProperty("java.util.secureRandomSeed");
375 jsr166 1.55 if (Boolean.parseBoolean(sec)) {
376 jsr166 1.41 byte[] seedBytes = java.security.SecureRandom.getSeed(8);
377     long s = (long)seedBytes[0] & 0xffL;
378     for (int i = 1; i < 8; ++i)
379     s = (s << 8) | ((long)seedBytes[i] & 0xffL);
380     seeder.set(s);
381     }
382     }
383 dl 1.64
384     @SuppressWarnings("serial")
385     private static final class ThreadLocalRandomProxy extends Random {
386     static final Random PROXY = new ThreadLocalRandomProxy();
387    
388     public int nextInt() {
389     return ThreadLocalRandom.current().nextInt();
390     }
391    
392     public long nextLong() {
393     return ThreadLocalRandom.current().nextLong();
394     }
395     }
396    
397     /**
398     * {@inheritDoc}
399     */
400     @Override
401     public boolean nextBoolean() {
402     return super.nextBoolean();
403     }
404    
405     /**
406     * {@inheritDoc}
407     */
408     @Override
409     public int nextInt() {
410     return mix32(nextSeed());
411     }
412    
413     /**
414     * {@inheritDoc}
415     * @throws IllegalArgumentException {@inheritDoc}
416     */
417     @Override
418     public int nextInt(int bound) {
419     return super.nextInt(bound);
420     }
421    
422     /**
423     * {@inheritDoc}
424     * @throws IllegalArgumentException {@inheritDoc}
425     */
426     @Override
427     public int nextInt(int origin, int bound) {
428     return super.nextInt(origin, bound);
429     }
430    
431     /**
432     * {@inheritDoc}
433     */
434     @Override
435     public long nextLong() {
436     return RandomSupport.mixMurmur64(nextSeed());
437     }
438    
439     /**
440     * {@inheritDoc}
441     * @throws IllegalArgumentException {@inheritDoc}
442     */
443     @Override
444     public long nextLong(long bound) {
445     return super.nextLong(bound);
446     }
447    
448     /**
449     * {@inheritDoc}
450     * @throws IllegalArgumentException {@inheritDoc}
451     */
452     @Override
453     public long nextLong(long origin, long bound) {
454     return super.nextLong(origin, bound);
455     }
456    
457     /**
458     * {@inheritDoc}
459     */
460     @Override
461     public float nextFloat() {
462     return super.nextFloat();
463     }
464    
465     /**
466     * {@inheritDoc}
467     * @throws IllegalArgumentException {@inheritDoc}
468     * @implNote {@inheritDoc}
469     */
470     @Override
471     public float nextFloat(float bound) {
472     return super.nextFloat(bound);
473     }
474    
475     /**
476     * {@inheritDoc}
477     * @throws IllegalArgumentException {@inheritDoc}
478     * @implNote {@inheritDoc}
479     */
480     @Override
481     public float nextFloat(float origin, float bound) {
482     return super.nextFloat(origin, bound);
483     }
484    
485     /**
486     * {@inheritDoc}
487     */
488     @Override
489     public double nextDouble() {
490     return super.nextDouble();
491     }
492    
493     /**
494     * {@inheritDoc}
495     * @throws IllegalArgumentException {@inheritDoc}
496     * @implNote {@inheritDoc}
497     */
498     @Override
499     public double nextDouble(double bound) {
500     return super.nextDouble(bound);
501     }
502    
503     /**
504     * {@inheritDoc}
505     * @throws IllegalArgumentException {@inheritDoc}
506     * @implNote {@inheritDoc}
507     */
508     @Override
509     public double nextDouble(double origin, double bound) {
510     return super.nextDouble(origin, bound);
511     }
512     /**
513     * {@inheritDoc}
514     * @throws IllegalArgumentException {@inheritDoc}
515     * @since 1.8
516     */
517     @Override
518     public IntStream ints(long streamSize) {
519     return AbstractSpliteratorGenerator.ints(ThreadLocalRandomProxy.PROXY, streamSize);
520     }
521    
522     /**
523     * {@inheritDoc}
524     * @implNote This method is implemented to be equivalent to
525     * {@code ints(Long.MAX_VALUE)}.
526     * @since 1.8
527     */
528     @Override
529     public IntStream ints() {
530     return AbstractSpliteratorGenerator.ints(ThreadLocalRandomProxy.PROXY);
531     }
532    
533     /**
534     * {@inheritDoc}
535     * @throws IllegalArgumentException {@inheritDoc}
536     * @since 1.8
537     */
538     @Override
539     public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) {
540     return AbstractSpliteratorGenerator.ints(ThreadLocalRandomProxy.PROXY, streamSize, randomNumberOrigin, randomNumberBound);
541     }
542    
543     /**
544     * {@inheritDoc}
545     * @implNote This method is implemented to be equivalent to
546     * {@code ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
547     * @throws IllegalArgumentException {@inheritDoc}
548     * @since 1.8
549     */
550     @Override
551     public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
552     return AbstractSpliteratorGenerator.ints(ThreadLocalRandomProxy.PROXY, randomNumberOrigin, randomNumberBound);
553     }
554    
555     /**
556     * {@inheritDoc}
557     * @throws IllegalArgumentException {@inheritDoc}
558     * @since 1.8
559     */
560     @Override
561     public LongStream longs(long streamSize) {
562     return AbstractSpliteratorGenerator.longs(ThreadLocalRandomProxy.PROXY, streamSize);
563     }
564    
565     /**
566     * {@inheritDoc}
567     * @implNote This method is implemented to be equivalent to
568     * {@code longs(Long.MAX_VALUE)}.
569     * @since 1.8
570     */
571     @Override
572     public LongStream longs() {
573     return AbstractSpliteratorGenerator.longs(ThreadLocalRandomProxy.PROXY);
574     }
575    
576     /**
577     * {@inheritDoc}
578     * @throws IllegalArgumentException {@inheritDoc}
579     * @since 1.8
580     */
581     @Override
582     public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound) {
583     return AbstractSpliteratorGenerator.longs(ThreadLocalRandomProxy.PROXY, streamSize, randomNumberOrigin, randomNumberBound);
584     }
585    
586     /**
587     * {@inheritDoc}
588     * @implNote This method is implemented to be equivalent to
589     * {@code longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
590     * @throws IllegalArgumentException {@inheritDoc}
591     * @since 1.8
592     */
593     @Override
594     public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
595     return AbstractSpliteratorGenerator.longs(ThreadLocalRandomProxy.PROXY, randomNumberOrigin, randomNumberBound);
596     }
597    
598     /**
599     * {@inheritDoc}
600     * @throws IllegalArgumentException {@inheritDoc}
601     * @since 1.8
602     */
603     @Override
604     public DoubleStream doubles(long streamSize) {
605     return AbstractSpliteratorGenerator.doubles(ThreadLocalRandomProxy.PROXY, streamSize);
606     }
607    
608     /**
609     * {@inheritDoc}
610     * @implNote This method is implemented to be equivalent to
611     * {@code doubles(Long.MAX_VALUE)}.
612     * @since 1.8
613     */
614     @Override
615     public DoubleStream doubles() {
616     return AbstractSpliteratorGenerator.doubles(ThreadLocalRandomProxy.PROXY);
617     }
618    
619     /**
620     * {@inheritDoc}
621     * @throws IllegalArgumentException {@inheritDoc}
622     * @since 1.8
623     */
624     @Override
625     public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
626     return AbstractSpliteratorGenerator.doubles(ThreadLocalRandomProxy.PROXY, streamSize, randomNumberOrigin, randomNumberBound);
627     }
628    
629     /**
630     * {@inheritDoc}
631     * @implNote This method is implemented to be equivalent to
632     * {@code doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
633     * @throws IllegalArgumentException {@inheritDoc}
634     * @since 1.8
635     */
636     @Override
637     public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
638     return AbstractSpliteratorGenerator.doubles(ThreadLocalRandomProxy.PROXY, randomNumberOrigin, randomNumberBound);
639     }
640    
641 jsr166 1.1 }