jaroslav@1890: /*
jaroslav@1890: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jaroslav@1890: *
jaroslav@1890: * This code is free software; you can redistribute it and/or modify it
jaroslav@1890: * under the terms of the GNU General Public License version 2 only, as
jaroslav@1890: * published by the Free Software Foundation. Oracle designates this
jaroslav@1890: * particular file as subject to the "Classpath" exception as provided
jaroslav@1890: * by Oracle in the LICENSE file that accompanied this code.
jaroslav@1890: *
jaroslav@1890: * This code is distributed in the hope that it will be useful, but WITHOUT
jaroslav@1890: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jaroslav@1890: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jaroslav@1890: * version 2 for more details (a copy is included in the LICENSE file that
jaroslav@1890: * accompanied this code).
jaroslav@1890: *
jaroslav@1890: * You should have received a copy of the GNU General Public License version
jaroslav@1890: * 2 along with this work; if not, write to the Free Software Foundation,
jaroslav@1890: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jaroslav@1890: *
jaroslav@1890: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jaroslav@1890: * or visit www.oracle.com if you need additional information or have any
jaroslav@1890: * questions.
jaroslav@1890: */
jaroslav@1890:
jaroslav@1890: /*
jaroslav@1890: * This file is available under and governed by the GNU General Public
jaroslav@1890: * License version 2 only, as published by the Free Software Foundation.
jaroslav@1890: * However, the following notice accompanied the original version of this
jaroslav@1890: * file:
jaroslav@1890: *
jaroslav@1890: * Written by Doug Lea with assistance from members of JCP JSR-166
jaroslav@1890: * Expert Group and released to the public domain, as explained at
jaroslav@1890: * http://creativecommons.org/publicdomain/zero/1.0/
jaroslav@1890: */
jaroslav@1890:
jaroslav@1890: package java.util.concurrent;
jaroslav@1890:
jaroslav@1890: import java.util.Random;
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * A random number generator isolated to the current thread. Like the
jaroslav@1890: * global {@link java.util.Random} generator used by the {@link
jaroslav@1890: * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
jaroslav@1890: * with an internally generated seed that may not otherwise be
jaroslav@1890: * modified. When applicable, use of {@code ThreadLocalRandom} rather
jaroslav@1890: * than shared {@code Random} objects in concurrent programs will
jaroslav@1890: * typically encounter much less overhead and contention. Use of
jaroslav@1890: * {@code ThreadLocalRandom} is particularly appropriate when multiple
jaroslav@1890: * tasks (for example, each a {@link ForkJoinTask}) use random numbers
jaroslav@1890: * in parallel in thread pools.
jaroslav@1890: *
jaroslav@1890: *
Usages of this class should typically be of the form:
jaroslav@1890: * {@code ThreadLocalRandom.current().nextX(...)} (where
jaroslav@1890: * {@code X} is {@code Int}, {@code Long}, etc).
jaroslav@1890: * When all usages are of this form, it is never possible to
jaroslav@1890: * accidently share a {@code ThreadLocalRandom} across multiple threads.
jaroslav@1890: *
jaroslav@1890: *
This class also provides additional commonly used bounded random
jaroslav@1890: * generation methods.
jaroslav@1890: *
jaroslav@1890: * @since 1.7
jaroslav@1890: * @author Doug Lea
jaroslav@1890: */
jaroslav@1890: public class ThreadLocalRandom extends Random {
jaroslav@1890: // same constants as Random, but must be redeclared because private
jaroslav@1890: private static final long multiplier = 0x5DEECE66DL;
jaroslav@1890: private static final long addend = 0xBL;
jaroslav@1890: private static final long mask = (1L << 48) - 1;
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * The random seed. We can't use super.seed.
jaroslav@1890: */
jaroslav@1890: private long rnd;
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Initialization flag to permit calls to setSeed to succeed only
jaroslav@1890: * while executing the Random constructor. We can't allow others
jaroslav@1890: * since it would cause setting seed in one part of a program to
jaroslav@1890: * unintentionally impact other usages by the thread.
jaroslav@1890: */
jaroslav@1890: boolean initialized;
jaroslav@1890:
jaroslav@1890: // Padding to help avoid memory contention among seed updates in
jaroslav@1890: // different TLRs in the common case that they are located near
jaroslav@1890: // each other.
jaroslav@1890: private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * The actual ThreadLocal
jaroslav@1890: */
jaroslav@1890: private static final ThreadLocal localRandom =
jaroslav@1890: new ThreadLocal() {
jaroslav@1890: protected ThreadLocalRandom initialValue() {
jaroslav@1890: return new ThreadLocalRandom();
jaroslav@1890: }
jaroslav@1890: };
jaroslav@1890:
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Constructor called only by localRandom.initialValue.
jaroslav@1890: */
jaroslav@1890: ThreadLocalRandom() {
jaroslav@1890: super();
jaroslav@1890: initialized = true;
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Returns the current thread's {@code ThreadLocalRandom}.
jaroslav@1890: *
jaroslav@1890: * @return the current thread's {@code ThreadLocalRandom}
jaroslav@1890: */
jaroslav@1890: public static ThreadLocalRandom current() {
jaroslav@1890: return localRandom.get();
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Throws {@code UnsupportedOperationException}. Setting seeds in
jaroslav@1890: * this generator is not supported.
jaroslav@1890: *
jaroslav@1890: * @throws UnsupportedOperationException always
jaroslav@1890: */
jaroslav@1890: public void setSeed(long seed) {
jaroslav@1890: if (initialized)
jaroslav@1890: throw new UnsupportedOperationException();
jaroslav@1890: rnd = (seed ^ multiplier) & mask;
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: protected int next(int bits) {
jaroslav@1890: rnd = (rnd * multiplier + addend) & mask;
jaroslav@1890: return (int) (rnd >>> (48-bits));
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Returns a pseudorandom, uniformly distributed value between the
jaroslav@1890: * given least value (inclusive) and bound (exclusive).
jaroslav@1890: *
jaroslav@1890: * @param least the least value returned
jaroslav@1890: * @param bound the upper bound (exclusive)
jaroslav@1890: * @throws IllegalArgumentException if least greater than or equal
jaroslav@1890: * to bound
jaroslav@1890: * @return the next value
jaroslav@1890: */
jaroslav@1890: public int nextInt(int least, int bound) {
jaroslav@1890: if (least >= bound)
jaroslav@1890: throw new IllegalArgumentException();
jaroslav@1890: return nextInt(bound - least) + least;
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Returns a pseudorandom, uniformly distributed value
jaroslav@1890: * between 0 (inclusive) and the specified value (exclusive).
jaroslav@1890: *
jaroslav@1890: * @param n the bound on the random number to be returned. Must be
jaroslav@1890: * positive.
jaroslav@1890: * @return the next value
jaroslav@1890: * @throws IllegalArgumentException if n is not positive
jaroslav@1890: */
jaroslav@1890: public long nextLong(long n) {
jaroslav@1890: if (n <= 0)
jaroslav@1890: throw new IllegalArgumentException("n must be positive");
jaroslav@1890: // Divide n by two until small enough for nextInt. On each
jaroslav@1890: // iteration (at most 31 of them but usually much less),
jaroslav@1890: // randomly choose both whether to include high bit in result
jaroslav@1890: // (offset) and whether to continue with the lower vs upper
jaroslav@1890: // half (which makes a difference only if odd).
jaroslav@1890: long offset = 0;
jaroslav@1890: while (n >= Integer.MAX_VALUE) {
jaroslav@1890: int bits = next(2);
jaroslav@1890: long half = n >>> 1;
jaroslav@1890: long nextn = ((bits & 2) == 0) ? half : n - half;
jaroslav@1890: if ((bits & 1) == 0)
jaroslav@1890: offset += n - nextn;
jaroslav@1890: n = nextn;
jaroslav@1890: }
jaroslav@1890: return offset + nextInt((int) n);
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Returns a pseudorandom, uniformly distributed value between the
jaroslav@1890: * given least value (inclusive) and bound (exclusive).
jaroslav@1890: *
jaroslav@1890: * @param least the least value returned
jaroslav@1890: * @param bound the upper bound (exclusive)
jaroslav@1890: * @return the next value
jaroslav@1890: * @throws IllegalArgumentException if least greater than or equal
jaroslav@1890: * to bound
jaroslav@1890: */
jaroslav@1890: public long nextLong(long least, long bound) {
jaroslav@1890: if (least >= bound)
jaroslav@1890: throw new IllegalArgumentException();
jaroslav@1890: return nextLong(bound - least) + least;
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Returns a pseudorandom, uniformly distributed {@code double} value
jaroslav@1890: * between 0 (inclusive) and the specified value (exclusive).
jaroslav@1890: *
jaroslav@1890: * @param n the bound on the random number to be returned. Must be
jaroslav@1890: * positive.
jaroslav@1890: * @return the next value
jaroslav@1890: * @throws IllegalArgumentException if n is not positive
jaroslav@1890: */
jaroslav@1890: public double nextDouble(double n) {
jaroslav@1890: if (n <= 0)
jaroslav@1890: throw new IllegalArgumentException("n must be positive");
jaroslav@1890: return nextDouble() * n;
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: /**
jaroslav@1890: * Returns a pseudorandom, uniformly distributed value between the
jaroslav@1890: * given least value (inclusive) and bound (exclusive).
jaroslav@1890: *
jaroslav@1890: * @param least the least value returned
jaroslav@1890: * @param bound the upper bound (exclusive)
jaroslav@1890: * @return the next value
jaroslav@1890: * @throws IllegalArgumentException if least greater than or equal
jaroslav@1890: * to bound
jaroslav@1890: */
jaroslav@1890: public double nextDouble(double least, double bound) {
jaroslav@1890: if (least >= bound)
jaroslav@1890: throw new IllegalArgumentException();
jaroslav@1890: return nextDouble() * (bound - least) + least;
jaroslav@1890: }
jaroslav@1890:
jaroslav@1890: private static final long serialVersionUID = -5851777807851030925L;
jaroslav@1890: }