ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/Random.java
(Generate patch)

Comparing jsr166/src/main/java/util/Random.java (file contents):
Revision 1.19 by jsr166, Tue Jan 30 03:46:41 2007 UTC vs.
Revision 1.30 by jsr166, Mon Jun 6 19:00:28 2011 UTC

# Line 1 | Line 1
1   /*
2 < * %W% %E%
2 > * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
3 > * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4   *
5 < * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
6 < * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
5 > * This code is free software; you can redistribute it and/or modify it
6 > * under the terms of the GNU General Public License version 2 only, as
7 > * published by the Free Software Foundation.  Oracle designates this
8 > * particular file as subject to the "Classpath" exception as provided
9 > * by Oracle in the LICENSE file that accompanied this code.
10 > *
11 > * This code is distributed in the hope that it will be useful, but WITHOUT
12 > * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 > * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 > * version 2 for more details (a copy is included in the LICENSE file that
15 > * accompanied this code).
16 > *
17 > * You should have received a copy of the GNU General Public License version
18 > * 2 along with this work; if not, write to the Free Software Foundation,
19 > * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 > *
21 > * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 > * or visit www.oracle.com if you need additional information or have any
23 > * questions.
24   */
25  
26   package java.util;
# Line 14 | Line 32 | import sun.misc.Unsafe;
32   * An instance of this class is used to generate a stream of
33   * pseudorandom numbers. The class uses a 48-bit seed, which is
34   * modified using a linear congruential formula. (See Donald Knuth,
35 < * <i>The Art of Computer Programming, Volume 3</i>, Section 3.2.1.)
35 > * <i>The Art of Computer Programming, Volume 2</i>, Section 3.2.1.)
36   * <p>
37   * If two instances of {@code Random} are created with the same
38   * seed, and the same sequence of method calls is made for each, they
# Line 32 | Line 50 | import sun.misc.Unsafe;
50   * <p>
51   * Many applications will find the method {@link Math#random} simpler to use.
52   *
53 + * <p>Instances of {@code java.util.Random} are threadsafe.
54 + * However, the concurrent use of the same {@code java.util.Random}
55 + * instance across threads may encounter contention and consequent
56 + * poor performance. Consider instead using
57 + * {@link java.util.concurrent.ThreadLocalRandom} in multithreaded
58 + * designs.
59 + *
60 + * <p>Instances of {@code java.util.Random} are not cryptographically
61 + * secure.  Consider instead using {@link java.security.SecureRandom} to
62 + * get a cryptographically secure pseudo-random number generator for use
63 + * by security-sensitive applications.
64 + *
65   * @author  Frank Yellin
36 * @version %I%, %G%
66   * @since   1.0
67   */
68   public
# Line 48 | Line 77 | class Random implements java.io.Serializ
77       */
78      private final AtomicLong seed;
79  
80 <    private final static long multiplier = 0x5DEECE66DL;
81 <    private final static long addend = 0xBL;
82 <    private final static long mask = (1L << 48) - 1;
80 >    private static final long multiplier = 0x5DEECE66DL;
81 >    private static final long addend = 0xBL;
82 >    private static final long mask = (1L << 48) - 1;
83  
84      /**
85       * Creates a new random number generator. This constructor sets
86       * the seed of the random number generator to a value very likely
87       * to be distinct from any other invocation of this constructor.
88       */
89 <    public Random() { this(++seedUniquifier + System.nanoTime()); }
90 <    private static volatile long seedUniquifier = 8682522807148012L;
89 >    public Random() {
90 >        this(seedUniquifier() ^ System.nanoTime());
91 >    }
92 >
93 >    private static long seedUniquifier() {
94 >        // L'Ecuyer, "Tables of Linear Congruential Generators of
95 >        // Different Sizes and Good Lattice Structure", 1999
96 >        for (;;) {
97 >            long current = seedUniquifier.get();
98 >            long next = current * 181783497276652981L;
99 >            if (seedUniquifier.compareAndSet(current, next))
100 >                return next;
101 >        }
102 >    }
103 >
104 >    private static final AtomicLong seedUniquifier
105 >        = new AtomicLong(8682522807148012L);
106  
107      /**
108       * Creates a new random number generator using a single {@code long} seed.
# Line 74 | Line 118 | class Random implements java.io.Serializ
118       * @see   #setSeed(long)
119       */
120      public Random(long seed) {
121 <        this.seed = new AtomicLong(0L);
122 <        setSeed(seed);
121 >        if (getClass() == Random.class)
122 >            this.seed = new AtomicLong(initialScramble(seed));
123 >        else {
124 >            // subclass might have overriden setSeed
125 >            this.seed = new AtomicLong();
126 >            setSeed(seed);
127 >        }
128 >    }
129 >
130 >    private static long initialScramble(long seed) {
131 >        return (seed ^ multiplier) & mask;
132      }
133  
134      /**
# Line 98 | Line 151 | class Random implements java.io.Serializ
151       * @param seed the initial seed
152       */
153      synchronized public void setSeed(long seed) {
154 <        seed = (seed ^ multiplier) & mask;
155 <        this.seed.set(seed);
103 <        haveNextNextGaussian = false;
154 >        this.seed.set(initialScramble(seed));
155 >        haveNextNextGaussian = false;
156      }
157  
158      /**
# Line 132 | Line 184 | class Random implements java.io.Serializ
184          long oldseed, nextseed;
185          AtomicLong seed = this.seed;
186          do {
187 <            oldseed = seed.get();
188 <            nextseed = (oldseed * multiplier + addend) & mask;
187 >            oldseed = seed.get();
188 >            nextseed = (oldseed * multiplier + addend) & mask;
189          } while (!seed.compareAndSet(oldseed, nextseed));
190          return (int)(nextseed >>> (48 - bits));
191      }
# Line 158 | Line 210 | class Random implements java.io.Serializ
210       * @since  1.1
211       */
212      public void nextBytes(byte[] bytes) {
213 <        for (int i = 0, len = bytes.length; i < len; )
214 <            for (int rnd = nextInt(),
215 <                     n = Math.min(len - i, Integer.SIZE/Byte.SIZE);
216 <                 n-- > 0; rnd >>= Byte.SIZE)
217 <                bytes[i++] = (byte)rnd;
213 >        for (int i = 0, len = bytes.length; i < len; )
214 >            for (int rnd = nextInt(),
215 >                     n = Math.min(len - i, Integer.SIZE/Byte.SIZE);
216 >                 n-- > 0; rnd >>= Byte.SIZE)
217 >                bytes[i++] = (byte)rnd;
218      }
219  
220      /**
# Line 184 | Line 236 | class Random implements java.io.Serializ
236       *         value from this random number generator's sequence
237       */
238      public int nextInt() {
239 <        return next(32);
239 >        return next(32);
240      }
241  
242      /**
# Line 235 | Line 287 | class Random implements java.io.Serializ
287       * successive calls to this method if n is a small power of two.
288       *
289       * @param n the bound on the random number to be returned.  Must be
290 <     *        positive.
290 >     *        positive.
291       * @return the next pseudorandom, uniformly distributed {@code int}
292       *         value between {@code 0} (inclusive) and {@code n} (exclusive)
293       *         from this random number generator's sequence
294 <     * @exception IllegalArgumentException if n is not positive
294 >     * @throws IllegalArgumentException if n is not positive
295       * @since 1.2
296       */
297  
# Line 299 | Line 351 | class Random implements java.io.Serializ
351       *
352       * @return the next pseudorandom, uniformly distributed
353       *         {@code boolean} value from this random number generator's
354 <     *         sequence
354 >     *         sequence
355       * @since 1.2
356       */
357      public boolean nextBoolean() {
358 <        return next(1) != 0;
358 >        return next(1) != 0;
359      }
360  
361      /**
# Line 390 | Line 442 | class Random implements java.io.Serializ
442       */
443      public double nextDouble() {
444          return (((long)(next(26)) << 27) + next(27))
445 <            / (double)(1L << 53);
445 >            / (double)(1L << 53);
446      }
447  
448      private double nextNextGaussian;
# Line 444 | Line 496 | class Random implements java.io.Serializ
496      synchronized public double nextGaussian() {
497          // See Knuth, ACP, Section 3.4.1 Algorithm C.
498          if (haveNextNextGaussian) {
499 <            haveNextNextGaussian = false;
500 <            return nextNextGaussian;
501 <        } else {
499 >            haveNextNextGaussian = false;
500 >            return nextNextGaussian;
501 >        } else {
502              double v1, v2, s;
503 <            do {
503 >            do {
504                  v1 = 2 * nextDouble() - 1; // between -1 and 1
505 <                v2 = 2 * nextDouble() - 1; // between -1 and 1
505 >                v2 = 2 * nextDouble() - 1; // between -1 and 1
506                  s = v1 * v1 + v2 * v2;
507 <            } while (s >= 1 || s == 0);
508 <            double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
509 <            nextNextGaussian = v2 * multiplier;
510 <            haveNextNextGaussian = true;
511 <            return v1 * multiplier;
507 >            } while (s >= 1 || s == 0);
508 >            double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
509 >            nextNextGaussian = v2 * multiplier;
510 >            haveNextNextGaussian = true;
511 >            return v1 * multiplier;
512          }
513      }
514  
# Line 485 | Line 537 | class Random implements java.io.Serializ
537  
538          ObjectInputStream.GetField fields = s.readFields();
539  
540 <        // The seed is read in as {@code long} for
541 <        // historical reasons, but it is converted to an AtomicLong.
542 <        long seedVal = (long) fields.get("seed", -1L);
540 >        // The seed is read in as {@code long} for
541 >        // historical reasons, but it is converted to an AtomicLong.
542 >        long seedVal = fields.get("seed", -1L);
543          if (seedVal < 0)
544            throw new java.io.StreamCorruptedException(
545                                "Random: invalid seed");
# Line 500 | Line 552 | class Random implements java.io.Serializ
552       * Save the {@code Random} instance to a stream.
553       */
554      synchronized private void writeObject(ObjectOutputStream s)
555 <        throws IOException {
555 >        throws IOException {
556  
557          // set the values of the Serializable fields
558          ObjectOutputStream.PutField fields = s.putFields();
559  
560 <        // The seed is serialized as a long for historical reasons.
560 >        // The seed is serialized as a long for historical reasons.
561          fields.put("seed", seed.get());
562          fields.put("nextNextGaussian", nextNextGaussian);
563          fields.put("haveNextNextGaussian", haveNextNextGaussian);
# Line 521 | Line 573 | class Random implements java.io.Serializ
573          try {
574              seedOffset = unsafe.objectFieldOffset
575                  (Random.class.getDeclaredField("seed"));
576 <        } catch (Exception ex) { throw new Error(ex); }
576 >        } catch (Exception ex) { throw new Error(ex); }
577      }
578      private void resetSeed(long seedVal) {
579          unsafe.putObjectVolatile(this, seedOffset, new AtomicLong(seedVal));

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines