RandomRegistry.java
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 &mdash; <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