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: }