1 /*
2 * Copyright 2009 Red Hat, Inc.
3 *
4 * Red Hat licenses this file to you under the Apache License, version 2.0
5 * (the "License"); you may not use this file except in compliance with the
6 * License. You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17 /*
18 * Written by Doug Lea with assistance from members of JCP JSR-166
19 * Expert Group and released to the public domain, as explained at
20 * http://creativecommons.org/licenses/publicdomain
21 */
22
23 package org.jboss.netty.util.internal;
24
25 import java.util.Random;
26
27 /**
28 * A random number generator isolated to the current thread. Like the
29 * global {@link java.util.Random} generator used by the {@link
30 * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
31 * with an internally generated seed that may not otherwise be
32 * modified. When applicable, use of {@code ThreadLocalRandom} rather
33 * than shared {@code Random} objects in concurrent programs will
34 * typically encounter much less overhead and contention. Use of
35 * {@code ThreadLocalRandom} is particularly appropriate when multiple
36 * tasks use random numbers in parallel in thread pools.
37 *
38 * <p>Usages of this class should typically be of the form:
39 * {@code ThreadLocalRandom.current().nextX(...)} (where
40 * {@code X} is {@code Int}, {@code Long}, etc).
41 * When all usages are of this form, it is never possible to
42 * accidently share a {@code ThreadLocalRandom} across multiple threads.
43 *
44 * <p>This class also provides additional commonly used bounded random
45 * generation methods.
46 *
47 * @since 1.7
48 * @author Doug Lea
49 */
50 final class ThreadLocalRandom extends Random {
51 // same constants as Random, but must be redeclared because private
52 private final static long multiplier = 0x5DEECE66DL;
53 private final static long addend = 0xBL;
54 private final static long mask = (1L << 48) - 1;
55
56 /**
57 * The random seed. We can't use super.seed.
58 */
59 private long rnd;
60
61 /**
62 * Initialization flag to permit the first and only allowed call
63 * to setSeed (inside Random constructor) to succeed. We can't
64 * allow others since it would cause setting seed in one part of a
65 * program to unintentionally impact other usages by the thread.
66 */
67 private boolean initialized;
68
69 // Padding to help avoid memory contention among seed updates in
70 // different TLRs in the common case that they are located near
71 // each other.
72 @SuppressWarnings("unused")
73 private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
74
75 /**
76 * The actual ThreadLocal
77 */
78 private static final ThreadLocal<ThreadLocalRandom> localRandom =
79 new ThreadLocal<ThreadLocalRandom>() {
80 @Override
81 protected ThreadLocalRandom initialValue() {
82 return new ThreadLocalRandom();
83 }
84 };
85
86
87 /**
88 * Constructor called only by localRandom.initialValue.
89 * We rely on the fact that the superclass no-arg constructor
90 * invokes setSeed exactly once to initialize.
91 */
92 ThreadLocalRandom() {
93 super();
94 }
95
96 /**
97 * Returns the current thread's {@code ThreadLocalRandom}.
98 *
99 * @return the current thread's {@code ThreadLocalRandom}
100 */
101 static ThreadLocalRandom current() {
102 return localRandom.get();
103 }
104
105 /**
106 * Throws {@code UnsupportedOperationException}. Setting seeds in
107 * this generator is not supported.
108 *
109 * @throws UnsupportedOperationException always
110 */
111 @Override
112 public void setSeed(long seed) {
113 if (initialized) {
114 throw new UnsupportedOperationException();
115 }
116 initialized = true;
117 rnd = (seed ^ multiplier) & mask;
118 }
119
120 @Override
121 protected int next(int bits) {
122 rnd = rnd * multiplier + addend & mask;
123 return (int) (rnd >>> 48-bits);
124 }
125
126 private static final long serialVersionUID = -5851777807851030925L;
127 }