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.15 by jsr166, Thu Feb 16 08:17:21 2006 UTC vs.
Revision 1.32 by dl, Wed Jan 16 19:01:22 2013 UTC

# Line 1 | Line 1
1   /*
2 < * %W% %E%
2 > * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
3 > * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4   *
5 < * Copyright 2006 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;
27   import java.io.*;
28   import java.util.concurrent.atomic.AtomicLong;
29 + import java.util.stream.IntStream;
30 + import java.util.stream.Streams;
31 +
32   import sun.misc.Unsafe;
33  
34   /**
35   * An instance of this class is used to generate a stream of
36   * pseudorandom numbers. The class uses a 48-bit seed, which is
37   * modified using a linear congruential formula. (See Donald Knuth,
38 < * <i>The Art of Computer Programming, Volume 3</i>, Section 3.2.1.)
38 > * <i>The Art of Computer Programming, Volume 2</i>, Section 3.2.1.)
39   * <p>
40   * If two instances of {@code Random} are created with the same
41   * seed, and the same sequence of method calls is made for each, they
# Line 32 | Line 53 | import sun.misc.Unsafe;
53   * <p>
54   * Many applications will find the method {@link Math#random} simpler to use.
55   *
56 + * <p>Instances of {@code java.util.Random} are threadsafe.
57 + * However, the concurrent use of the same {@code java.util.Random}
58 + * instance across threads may encounter contention and consequent
59 + * poor performance. Consider instead using
60 + * {@link java.util.concurrent.ThreadLocalRandom} in multithreaded
61 + * designs.
62 + *
63 + * <p>Instances of {@code java.util.Random} are not cryptographically
64 + * secure.  Consider instead using {@link java.security.SecureRandom} to
65 + * get a cryptographically secure pseudo-random number generator for use
66 + * by security-sensitive applications.
67 + *
68   * @author  Frank Yellin
36 * @version %I%, %G%
69   * @since   1.0
70   */
71   public
# Line 45 | Line 77 | class Random implements java.io.Serializ
77       * The internal state associated with this pseudorandom number generator.
78       * (The specs for the methods in this class describe the ongoing
79       * computation of this value.)
48     *
49     * @serial
80       */
81      private final AtomicLong seed;
82  
83 <    private final static long multiplier = 0x5DEECE66DL;
84 <    private final static long addend = 0xBL;
85 <    private final static long mask = (1L << 48) - 1;
83 >    private static final long multiplier = 0x5DEECE66DL;
84 >    private static final long addend = 0xBL;
85 >    private static final long mask = (1L << 48) - 1;
86  
87      /**
88       * Creates a new random number generator. This constructor sets
89       * the seed of the random number generator to a value very likely
90       * to be distinct from any other invocation of this constructor.
91       */
92 <    public Random() { this(++seedUniquifier + System.nanoTime()); }
93 <    private static volatile long seedUniquifier = 8682522807148012L;
92 >    public Random() {
93 >        this(seedUniquifier() ^ System.nanoTime());
94 >    }
95 >
96 >    private static long seedUniquifier() {
97 >        // L'Ecuyer, "Tables of Linear Congruential Generators of
98 >        // Different Sizes and Good Lattice Structure", 1999
99 >        for (;;) {
100 >            long current = seedUniquifier.get();
101 >            long next = current * 181783497276652981L;
102 >            if (seedUniquifier.compareAndSet(current, next))
103 >                return next;
104 >        }
105 >    }
106 >
107 >    private static final AtomicLong seedUniquifier
108 >        = new AtomicLong(8682522807148012L);
109  
110      /**
111       * Creates a new random number generator using a single {@code long} seed.
# Line 76 | Line 121 | class Random implements java.io.Serializ
121       * @see   #setSeed(long)
122       */
123      public Random(long seed) {
124 <        this.seed = new AtomicLong(0L);
125 <        setSeed(seed);
124 >        if (getClass() == Random.class)
125 >            this.seed = new AtomicLong(initialScramble(seed));
126 >        else {
127 >            // subclass might have overriden setSeed
128 >            this.seed = new AtomicLong();
129 >            setSeed(seed);
130 >        }
131 >    }
132 >
133 >    private static long initialScramble(long seed) {
134 >        return (seed ^ multiplier) & mask;
135      }
136  
137      /**
# Line 100 | Line 154 | class Random implements java.io.Serializ
154       * @param seed the initial seed
155       */
156      synchronized public void setSeed(long seed) {
157 <        seed = (seed ^ multiplier) & mask;
158 <        this.seed.set(seed);
105 <        haveNextNextGaussian = false;
157 >        this.seed.set(initialScramble(seed));
158 >        haveNextNextGaussian = false;
159      }
160  
161      /**
# Line 134 | Line 187 | class Random implements java.io.Serializ
187          long oldseed, nextseed;
188          AtomicLong seed = this.seed;
189          do {
190 <            oldseed = seed.get();
191 <            nextseed = (oldseed * multiplier + addend) & mask;
190 >            oldseed = seed.get();
191 >            nextseed = (oldseed * multiplier + addend) & mask;
192          } while (!seed.compareAndSet(oldseed, nextseed));
193          return (int)(nextseed >>> (48 - bits));
194      }
# Line 160 | Line 213 | class Random implements java.io.Serializ
213       * @since  1.1
214       */
215      public void nextBytes(byte[] bytes) {
216 <        for (int i = 0, len = bytes.length; i < len; )
217 <            for (int rnd = nextInt(),
218 <                     n = Math.min(len - i, Integer.SIZE/Byte.SIZE);
219 <                 n-- > 0; rnd >>= Byte.SIZE)
220 <                bytes[i++] = (byte)rnd;
216 >        for (int i = 0, len = bytes.length; i < len; )
217 >            for (int rnd = nextInt(),
218 >                     n = Math.min(len - i, Integer.SIZE/Byte.SIZE);
219 >                 n-- > 0; rnd >>= Byte.SIZE)
220 >                bytes[i++] = (byte)rnd;
221      }
222  
223      /**
# Line 186 | Line 239 | class Random implements java.io.Serializ
239       *         value from this random number generator's sequence
240       */
241      public int nextInt() {
242 <        return next(32);
242 >        return next(32);
243      }
244  
245      /**
# Line 237 | Line 290 | class Random implements java.io.Serializ
290       * successive calls to this method if n is a small power of two.
291       *
292       * @param n the bound on the random number to be returned.  Must be
293 <     *        positive.
293 >     *        positive.
294       * @return the next pseudorandom, uniformly distributed {@code int}
295       *         value between {@code 0} (inclusive) and {@code n} (exclusive)
296       *         from this random number generator's sequence
297 <     * @exception IllegalArgumentException if n is not positive
297 >     * @throws IllegalArgumentException if n is not positive
298       * @since 1.2
299       */
300  
# Line 301 | Line 354 | class Random implements java.io.Serializ
354       *
355       * @return the next pseudorandom, uniformly distributed
356       *         {@code boolean} value from this random number generator's
357 <     *         sequence
357 >     *         sequence
358       * @since 1.2
359       */
360      public boolean nextBoolean() {
361 <        return next(1) != 0;
361 >        return next(1) != 0;
362      }
363  
364      /**
# Line 392 | Line 445 | class Random implements java.io.Serializ
445       */
446      public double nextDouble() {
447          return (((long)(next(26)) << 27) + next(27))
448 <            / (double)(1L << 53);
448 >            / (double)(1L << 53);
449      }
450  
451      private double nextNextGaussian;
# Line 446 | Line 499 | class Random implements java.io.Serializ
499      synchronized public double nextGaussian() {
500          // See Knuth, ACP, Section 3.4.1 Algorithm C.
501          if (haveNextNextGaussian) {
502 <            haveNextNextGaussian = false;
503 <            return nextNextGaussian;
504 <        } else {
502 >            haveNextNextGaussian = false;
503 >            return nextNextGaussian;
504 >        } else {
505              double v1, v2, s;
506 <            do {
506 >            do {
507                  v1 = 2 * nextDouble() - 1; // between -1 and 1
508 <                v2 = 2 * nextDouble() - 1; // between -1 and 1
508 >                v2 = 2 * nextDouble() - 1; // between -1 and 1
509                  s = v1 * v1 + v2 * v2;
510 <            } while (s >= 1 || s == 0);
511 <            double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
512 <            nextNextGaussian = v2 * multiplier;
513 <            haveNextNextGaussian = true;
514 <            return v1 * multiplier;
510 >            } while (s >= 1 || s == 0);
511 >            double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
512 >            nextNextGaussian = v2 * multiplier;
513 >            haveNextNextGaussian = true;
514 >            return v1 * multiplier;
515          }
516      }
517  
518 +    public IntStream ints() {
519 +        return Streams.generateInt(this::nextInt);
520 +    }
521 +
522      /**
523       * Serializable fields for Random.
524       *
525 <     * @serialField    seed long;
525 >     * @serialField    seed long
526       *              seed for random computations
527 <     * @serialField    nextNextGaussian double;
527 >     * @serialField    nextNextGaussian double
528       *              next Gaussian to be returned
529       * @serialField      haveNextNextGaussian boolean
530       *              nextNextGaussian is valid
# Line 487 | Line 544 | class Random implements java.io.Serializ
544  
545          ObjectInputStream.GetField fields = s.readFields();
546  
547 <        // The seed is read in as {@code long} for
548 <        // historical reasons, but it is converted to an AtomicLong.
549 <        long seedVal = (long) fields.get("seed", -1L);
547 >        // The seed is read in as {@code long} for
548 >        // historical reasons, but it is converted to an AtomicLong.
549 >        long seedVal = fields.get("seed", -1L);
550          if (seedVal < 0)
551            throw new java.io.StreamCorruptedException(
552                                "Random: invalid seed");
# Line 502 | Line 559 | class Random implements java.io.Serializ
559       * Save the {@code Random} instance to a stream.
560       */
561      synchronized private void writeObject(ObjectOutputStream s)
562 <        throws IOException {
562 >        throws IOException {
563  
564          // set the values of the Serializable fields
565          ObjectOutputStream.PutField fields = s.putFields();
566  
567 <        // The seed is serialized as a long for historical reasons.
567 >        // The seed is serialized as a long for historical reasons.
568          fields.put("seed", seed.get());
569          fields.put("nextNextGaussian", nextNextGaussian);
570          fields.put("haveNextNextGaussian", haveNextNextGaussian);
# Line 523 | Line 580 | class Random implements java.io.Serializ
580          try {
581              seedOffset = unsafe.objectFieldOffset
582                  (Random.class.getDeclaredField("seed"));
583 <            } catch (Exception ex) { throw new Error(ex); }
583 >        } catch (Exception ex) { throw new Error(ex); }
584      }
585      private void resetSeed(long seedVal) {
586          unsafe.putObjectVolatile(this, seedOffset, new AtomicLong(seedVal));
587      }
531
588   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines