25 |
|
|
26 |
|
package java.util; |
27 |
|
|
28 |
+ |
import java.security.SecureRandom; |
29 |
|
import java.net.InetAddress; |
30 |
|
import java.util.concurrent.atomic.AtomicLong; |
30 |
– |
import java.util.Spliterator; |
31 |
|
import java.util.function.IntConsumer; |
32 |
|
import java.util.function.LongConsumer; |
33 |
|
import java.util.function.DoubleConsumer; |
39 |
|
/** |
40 |
|
* A generator of uniform pseudorandom values applicable for use in |
41 |
|
* (among other contexts) isolated parallel computations that may |
42 |
< |
* generate subtasks. Class SplittableRandom supports methods for |
42 |
> |
* generate subtasks. Class {@code SplittableRandom} supports methods for |
43 |
|
* producing pseudorandom numbers of type {@code int}, {@code long}, |
44 |
|
* and {@code double} with similar usages as for class |
45 |
|
* {@link java.util.Random} but differs in the following ways: |
77 |
|
* |
78 |
|
* </ul> |
79 |
|
* |
80 |
+ |
* <p>Instances of {@code SplittableRandom} are not cryptographically |
81 |
+ |
* secure. Consider instead using {@link java.security.SecureRandom} |
82 |
+ |
* in security-sensitive applications. Additionally, |
83 |
+ |
* default-constructed instances do not use a cryptographically random |
84 |
+ |
* seed unless the {@linkplain System#getProperty system property} |
85 |
+ |
* {@code java.util.secureRandomSeed} is set to {@code true}. |
86 |
+ |
* |
87 |
|
* @author Guy Steele |
88 |
|
* @author Doug Lea |
89 |
|
* @since 1.8 |
145 |
|
* cases, this split must be performed in a thread-safe manner, so |
146 |
|
* we use an AtomicLong to represent the seed rather than use an |
147 |
|
* explicit SplittableRandom. To bootstrap the seeder, we start |
148 |
< |
* off using a seed based on current time and host. This serves as |
149 |
< |
* a slimmed-down (and insecure) variant of SecureRandom that also |
148 |
> |
* off using a seed based on current time and host unless the |
149 |
> |
* SecureRandomSeed property is set. This serves as a |
150 |
> |
* slimmed-down (and insecure) variant of SecureRandom that also |
151 |
|
* avoids stalls that may occur when using /dev/random. |
152 |
|
* |
153 |
|
* It is a relatively simple matter to apply the basic design here |
229 |
|
/** |
230 |
|
* The seed generator for default constructors. |
231 |
|
*/ |
232 |
< |
private static final AtomicLong seeder = |
225 |
< |
new AtomicLong(mix64((((long)hashedHostAddress()) << 32) ^ |
226 |
< |
System.currentTimeMillis()) ^ |
227 |
< |
mix64(System.nanoTime())); |
232 |
> |
private static final AtomicLong seeder = new AtomicLong(initialSeed()); |
233 |
|
|
234 |
< |
/** |
235 |
< |
* Returns hash of local host IP address, if available; else 0. |
236 |
< |
*/ |
237 |
< |
private static int hashedHostAddress() { |
234 |
> |
private static long initialSeed() { |
235 |
> |
try { // ignore exceptions in accessing/parsing properties |
236 |
> |
String pp = System.getProperty |
237 |
> |
("java.util.secureRandomSeed"); |
238 |
> |
if (pp != null && pp.equalsIgnoreCase("true")) { |
239 |
> |
byte[] seedBytes = java.security.SecureRandom.getSeed(8); |
240 |
> |
long s = (long)(seedBytes[0]) & 0xffL; |
241 |
> |
for (int i = 1; i < 8; ++i) |
242 |
> |
s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); |
243 |
> |
return s; |
244 |
> |
} |
245 |
> |
} catch (Exception ignore) { |
246 |
> |
} |
247 |
> |
int hh = 0; // hashed host address |
248 |
|
try { |
249 |
< |
return InetAddress.getLocalHost().hashCode(); |
250 |
< |
} catch (Exception ex) { |
236 |
< |
return 0; |
249 |
> |
hh = InetAddress.getLocalHost().hashCode(); |
250 |
> |
} catch (Exception ignore) { |
251 |
|
} |
252 |
+ |
return (mix64((((long)hh) << 32) ^ System.currentTimeMillis()) ^ |
253 |
+ |
mix64(System.nanoTime())); |
254 |
|
} |
255 |
|
|
256 |
|
// IllegalArgumentException messages |
422 |
|
* Returns a pseudorandom {@code int} value between zero (inclusive) |
423 |
|
* and the specified bound (exclusive). |
424 |
|
* |
425 |
< |
* @param bound the bound on the random number to be returned. Must be |
410 |
< |
* positive. |
425 |
> |
* @param bound the upper bound (exclusive). Must be positive. |
426 |
|
* @return a pseudorandom {@code int} value between zero |
427 |
|
* (inclusive) and the bound (exclusive) |
428 |
|
* @throws IllegalArgumentException if {@code bound} is not positive |
474 |
|
* Returns a pseudorandom {@code long} value between zero (inclusive) |
475 |
|
* and the specified bound (exclusive). |
476 |
|
* |
477 |
< |
* @param bound the bound on the random number to be returned. Must be |
463 |
< |
* positive. |
477 |
> |
* @param bound the upper bound (exclusive). Must be positive. |
478 |
|
* @return a pseudorandom {@code long} value between zero |
479 |
|
* (inclusive) and the bound (exclusive) |
480 |
|
* @throws IllegalArgumentException if {@code bound} is not positive |
518 |
|
* (inclusive) and one (exclusive). |
519 |
|
* |
520 |
|
* @return a pseudorandom {@code double} value between zero |
521 |
< |
* (inclusive) and one (exclusive) |
521 |
> |
* (inclusive) and one (exclusive) |
522 |
|
*/ |
523 |
|
public double nextDouble() { |
524 |
|
return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT; |
528 |
|
* Returns a pseudorandom {@code double} value between 0.0 |
529 |
|
* (inclusive) and the specified bound (exclusive). |
530 |
|
* |
531 |
< |
* @param bound the bound on the random number to be returned. Must be |
518 |
< |
* positive. |
531 |
> |
* @param bound the upper bound (exclusive). Must be positive. |
532 |
|
* @return a pseudorandom {@code double} value between zero |
533 |
|
* (inclusive) and the bound (exclusive) |
534 |
|
* @throws IllegalArgumentException if {@code bound} is not positive |
546 |
|
* origin (inclusive) and bound (exclusive). |
547 |
|
* |
548 |
|
* @param origin the least value returned |
549 |
< |
* @param bound the upper bound |
549 |
> |
* @param bound the upper bound (exclusive) |
550 |
|
* @return a pseudorandom {@code double} value between the origin |
551 |
|
* (inclusive) and the bound (exclusive) |
552 |
|
* @throws IllegalArgumentException if {@code origin} is greater than |
607 |
|
|
608 |
|
/** |
609 |
|
* Returns a stream producing the given {@code streamSize} number |
610 |
< |
* of pseudorandom {@code int} values, each conforming to the |
611 |
< |
* given origin and bound. |
610 |
> |
* of pseudorandom {@code int} values from this generator and/or one split |
611 |
> |
* from it; each value conforms to the given origin (inclusive) and bound |
612 |
> |
* (exclusive). |
613 |
|
* |
614 |
|
* @param streamSize the number of values to generate |
615 |
< |
* @param randomNumberOrigin the origin of each random value |
616 |
< |
* @param randomNumberBound the bound of each random value |
615 |
> |
* @param randomNumberOrigin the origin (inclusive) of each random value |
616 |
> |
* @param randomNumberBound the bound (exclusive) of each random value |
617 |
|
* @return a stream of pseudorandom {@code int} values, |
618 |
< |
* each with the given origin and bound |
618 |
> |
* each with the given origin (inclusive) and bound (exclusive) |
619 |
|
* @throws IllegalArgumentException if {@code streamSize} is |
620 |
|
* less than zero, or {@code randomNumberOrigin} |
621 |
|
* is greater than or equal to {@code randomNumberBound} |
634 |
|
|
635 |
|
/** |
636 |
|
* Returns an effectively unlimited stream of pseudorandom {@code |
637 |
< |
* int} values, each conforming to the given origin and bound. |
637 |
> |
* int} values from this generator and/or one split from it; each value |
638 |
> |
* conforms to the given origin (inclusive) and bound (exclusive). |
639 |
|
* |
640 |
|
* @implNote This method is implemented to be equivalent to {@code |
641 |
|
* ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. |
642 |
|
* |
643 |
< |
* @param randomNumberOrigin the origin of each random value |
644 |
< |
* @param randomNumberBound the bound of each random value |
643 |
> |
* @param randomNumberOrigin the origin (inclusive) of each random value |
644 |
> |
* @param randomNumberBound the bound (exclusive) of each random value |
645 |
|
* @return a stream of pseudorandom {@code int} values, |
646 |
< |
* each with the given origin and bound |
646 |
> |
* each with the given origin (inclusive) and bound (exclusive) |
647 |
|
* @throws IllegalArgumentException if {@code randomNumberOrigin} |
648 |
|
* is greater than or equal to {@code randomNumberBound} |
649 |
|
*/ |
693 |
|
|
694 |
|
/** |
695 |
|
* Returns a stream producing the given {@code streamSize} number of |
696 |
< |
* pseudorandom {@code long} values, each conforming to the |
697 |
< |
* given origin and bound. |
696 |
> |
* pseudorandom {@code long} values from this generator and/or one split |
697 |
> |
* from it; each value conforms to the given origin (inclusive) and bound |
698 |
> |
* (exclusive). |
699 |
|
* |
700 |
|
* @param streamSize the number of values to generate |
701 |
< |
* @param randomNumberOrigin the origin of each random value |
702 |
< |
* @param randomNumberBound the bound of each random value |
701 |
> |
* @param randomNumberOrigin the origin (inclusive) of each random value |
702 |
> |
* @param randomNumberBound the bound (exclusive) of each random value |
703 |
|
* @return a stream of pseudorandom {@code long} values, |
704 |
< |
* each with the given origin and bound |
704 |
> |
* each with the given origin (inclusive) and bound (exclusive) |
705 |
|
* @throws IllegalArgumentException if {@code streamSize} is |
706 |
|
* less than zero, or {@code randomNumberOrigin} |
707 |
|
* is greater than or equal to {@code randomNumberBound} |
720 |
|
|
721 |
|
/** |
722 |
|
* Returns an effectively unlimited stream of pseudorandom {@code |
723 |
< |
* long} values, each conforming to the given origin and bound. |
723 |
> |
* long} values from this generator and/or one split from it; each value |
724 |
> |
* conforms to the given origin (inclusive) and bound (exclusive). |
725 |
|
* |
726 |
|
* @implNote This method is implemented to be equivalent to {@code |
727 |
|
* longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. |
728 |
|
* |
729 |
< |
* @param randomNumberOrigin the origin of each random value |
730 |
< |
* @param randomNumberBound the bound of each random value |
729 |
> |
* @param randomNumberOrigin the origin (inclusive) of each random value |
730 |
> |
* @param randomNumberBound the bound (exclusive) of each random value |
731 |
|
* @return a stream of pseudorandom {@code long} values, |
732 |
< |
* each with the given origin and bound |
732 |
> |
* each with the given origin (inclusive) and bound (exclusive) |
733 |
|
* @throws IllegalArgumentException if {@code randomNumberOrigin} |
734 |
|
* is greater than or equal to {@code randomNumberBound} |
735 |
|
*/ |
744 |
|
|
745 |
|
/** |
746 |
|
* Returns a stream producing the given {@code streamSize} number of |
747 |
< |
* pseudorandom {@code double} values, each between zero |
748 |
< |
* (inclusive) and one (exclusive). |
747 |
> |
* pseudorandom {@code double} values from this generator and/or one split |
748 |
> |
* from it; each value is between zero (inclusive) and one (exclusive). |
749 |
|
* |
750 |
|
* @param streamSize the number of values to generate |
751 |
|
* @return a stream of {@code double} values |
763 |
|
|
764 |
|
/** |
765 |
|
* Returns an effectively unlimited stream of pseudorandom {@code |
766 |
< |
* double} values, each between zero (inclusive) and one |
767 |
< |
* (exclusive). |
766 |
> |
* double} values from this generator and/or one split from it; each value |
767 |
> |
* is between zero (inclusive) and one (exclusive). |
768 |
|
* |
769 |
|
* @implNote This method is implemented to be equivalent to {@code |
770 |
|
* doubles(Long.MAX_VALUE)}. |
780 |
|
|
781 |
|
/** |
782 |
|
* Returns a stream producing the given {@code streamSize} number of |
783 |
< |
* pseudorandom {@code double} values, each conforming to the |
784 |
< |
* given origin and bound. |
783 |
> |
* pseudorandom {@code double} values from this generator and/or one split |
784 |
> |
* from it; each value conforms to the given origin (inclusive) and bound |
785 |
> |
* (exclusive). |
786 |
|
* |
787 |
|
* @param streamSize the number of values to generate |
788 |
< |
* @param randomNumberOrigin the origin of each random value |
789 |
< |
* @param randomNumberBound the bound of each random value |
788 |
> |
* @param randomNumberOrigin the origin (inclusive) of each random value |
789 |
> |
* @param randomNumberBound the bound (exclusive) of each random value |
790 |
|
* @return a stream of pseudorandom {@code double} values, |
791 |
< |
* each with the given origin and bound |
791 |
> |
* each with the given origin (inclusive) and bound (exclusive) |
792 |
|
* @throws IllegalArgumentException if {@code streamSize} is |
793 |
< |
* less than zero |
793 |
> |
* less than zero |
794 |
|
* @throws IllegalArgumentException if {@code randomNumberOrigin} |
795 |
|
* is greater than or equal to {@code randomNumberBound} |
796 |
|
*/ |
808 |
|
|
809 |
|
/** |
810 |
|
* Returns an effectively unlimited stream of pseudorandom {@code |
811 |
< |
* double} values, each conforming to the given origin and bound. |
811 |
> |
* double} values from this generator and/or one split from it; each value |
812 |
> |
* conforms to the given origin (inclusive) and bound (exclusive). |
813 |
|
* |
814 |
|
* @implNote This method is implemented to be equivalent to {@code |
815 |
|
* doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. |
816 |
|
* |
817 |
< |
* @param randomNumberOrigin the origin of each random value |
818 |
< |
* @param randomNumberBound the bound of each random value |
817 |
> |
* @param randomNumberOrigin the origin (inclusive) of each random value |
818 |
> |
* @param randomNumberBound the bound (exclusive) of each random value |
819 |
|
* @return a stream of pseudorandom {@code double} values, |
820 |
< |
* each with the given origin and bound |
820 |
> |
* each with the given origin (inclusive) and bound (exclusive) |
821 |
|
* @throws IllegalArgumentException if {@code randomNumberOrigin} |
822 |
|
* is greater than or equal to {@code randomNumberBound} |
823 |
|
*/ |