001 /*
002 * Java Genetic Algorithm Library (jenetics-1.5.0).
003 * Copyright (c) 2007-2013 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.util;
021
022 import static java.util.Objects.requireNonNull;
023
024 import java.util.Random;
025 import java.util.concurrent.ThreadLocalRandom;
026
027 import javolution.context.LocalContext;
028 import javolution.lang.Reference;
029
030 /**
031 * This class holds the {@link Random} engine used for the GA. The
032 * {@code RandomRegistry} is thread safe. The registry is initialized with the
033 * {@link ThreadLocalRandom} PRNG, which has a much better performance behavior
034 * than an instance of the {@code Random} class. Alternatively, you can
035 * initialize the registry with one of the PRNG, which are being part of the
036 * library.
037 * <p/>
038 *
039 * <b>Setup of a <i>global</i> PRNG</b>
040 *
041 * [code]
042 * public class GA {
043 * public static void main(final String[] args) {
044 * // Initialize the registry with a ThreadLocal instance of the PRGN.
045 * // This is the preferred way setting a new PRGN.
046 * RandomRegistry.setRandom(new LCG64ShiftRandom.ThreadLocal());
047 *
048 * // Using a thread safe variant of the PRGN. Leads to slower PRN
049 * // generation, but gives you the possibility to set a PRNG seed.
050 * RandomRegistry.setRandom(new LCG64ShiftRandom.ThreadSafe(1234));
051 *
052 * ...
053 * final GeneticAlgorithm<Float64Gene, Float64> ga = ...
054 * ga.evolve(100);
055 * }
056 * }
057 * [/code]
058 * <p/>
059 *
060 * <b>Setup of a <i>local</i> PRNG</b><br/>
061 *
062 * With the help of the {@link LocalContext} from the <a href="http://javolution.org/">
063 * Javolution</a> project you can temporarily (and locally) change the
064 * implementation of the PRNG.
065 *
066 * [code]
067 * public class GA {
068 * public static void main(final String[] args) {
069 * ...
070 * final GeneticAlgorithm<Float64Gene, Float64> ga = ...
071 *
072 * LocalContext.enter();
073 * try {
074 * RandomRegistry.setRandom(new LCG64ShiftRandom.ThreadSafe(1234));
075 * // Only the 'setup' step uses the new PRGN.
076 * ga.setup();
077 * } finally {
078 * LocalContext.exit(); // Restore the previous random engine.
079 * }
080 *
081 * ga.evolve(100);
082 * }
083 * }
084 * [/code]
085 * <p/>
086 *
087 * @see LocalContext
088 * @see Random
089 * @see ThreadLocalRandom
090 * @see LCG64ShiftRandom
091 *
092 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
093 * @since 1.0
094 * @version 1.2 — <em>$Date: 2013-12-05 $</em>
095 */
096 public final class RandomRegistry extends StaticObject {
097 private RandomRegistry() {}
098
099 private static final Reference<Random> TLOCAL_REF = new Ref<Random>() {
100 @Override
101 public Random get() {
102 return ThreadLocalRandom.current();
103 }
104 };
105
106 private static final LocalContext.Reference<Reference<? extends Random>>
107 RANDOM = new LocalContext.Reference<Reference<? extends Random>>(TLOCAL_REF);
108
109 /**
110 * Return the global {@link Random} object.
111 *
112 * @return the global {@link Random} object.
113 */
114 public static Random getRandom() {
115 return RANDOM.get().get();
116 }
117
118 /**
119 * Set the new global {@link Random} object for the GA. The given
120 * {@link Random} <b>must</b> be thread safe, which is the case for the
121 * default Java {@code Random} implementation.
122 * <p/>
123 * Setting a <i>thread-local</i> random object leads, in general, to a faster
124 * PRN generation, because the given {@code Random} engine don't have to be
125 * thread-safe.
126 *
127 * @see #setRandom(ThreadLocal)
128 *
129 * @param random the new global {@link Random} object for the GA.
130 * @throws NullPointerException if the {@code random} object is {@code null}.
131 */
132 public static void setRandom(final Random random) {
133 RANDOM.set(new RRef(random));
134 }
135
136 /**
137 * Set the new global {@link Random} object for the GA. The given
138 * {@link Random} don't have be thread safe, because the given
139 * {@link ThreadLocal} wrapper guarantees thread safety. Setting a
140 * <i>thread-local</i> random object leads, in general, to a faster
141 * PRN generation, when using a non-blocking PRNG. This is the preferred
142 * way for changing the PRNG.
143 *
144 * @param random the thread-local random engine to use.
145 * @throws NullPointerException if the {@code random} object is {@code null}.
146 */
147 public static void setRandom(final ThreadLocal<? extends Random> random) {
148 RANDOM.set(new TLRRef<>(random));
149 }
150
151 /**
152 * Set the random object to it's default value. The <i>default</i> used PRNG
153 * is the {@link ThreadLocalRandom} PRNG.
154 */
155 public static void reset() {
156 RANDOM.set(TLOCAL_REF);
157 }
158
159
160 /*
161 * Some helper Reference classes.
162 */
163
164 private static abstract class Ref<R> implements Reference<R> {
165 @Override public void set(final R random) {}
166 }
167
168 private final static class RRef extends Ref<Random> {
169 private final Random _random;
170 public RRef(final Random random) {
171 _random = requireNonNull(random, "Random");
172 }
173 @Override public final Random get() {
174 return _random;
175 }
176 }
177
178 private final static class TLRRef<R extends Random> extends Ref<R> {
179 private final ThreadLocal<R> _random;
180 public TLRRef(final ThreadLocal<R> random) {
181 _random = requireNonNull(random, "Random");
182 }
183 @Override public final R get() {
184 return _random.get();
185 }
186 }
187
188 }
189
190
191
192
|