超详细的逐句介绍Java高级接口之Random函数源码讲解(全)

一、Random函数

Random函数主要用于生成随机数的函数,这是在计算机测试时生成相应的测试数据的过程中很有用,下面我将从源码的角度进行Random函数的内部进行详细介绍。

二、Random函数源码详细介绍

首先,Random函数继承于java.io.Serializable 接口

public
class Random implements java.io.Serializable {
}

下面定义了一个下一个高斯数的初始化变量和标志位。

private double nextNextGaussian;
private boolean haveNextNextGaussian = false;

下面是random的通用串行ID

static final long serialVersionUID = 3905348978240129619L;

下面定义了random的种子

private final AtomicLong seed;

下面定义了乘数、加数掩码等初始化变量

    private static final long multiplier = 0x5DEECE66DL;
    private static final long addend = 0xBL;
    private static final long mask = (1L << 48) - 1;

    private static final double DOUBLE_UNIT = 0x1.0p-53;

下面主要了一些出错信息

	static final String BadBound = "bound must be positive";
    static final String BadRange = "bound must be greater than origin";
    static final String BadSize  = "size must be non-negative";

创建一个新的随机数生成器。此构造函数将随机数生成器的种子设置为一个很可能与此构造函数的任何其他调用不同的值。

public Random() {
        this(seedUniquifier() ^ System.nanoTime());
    }

下面定义种子唯一标志符

private static long seedUniquifier() {
        // L'Ecuyer, "Tables of Linear Congruential Generators of
        // Different Sizes and Good Lattice Structure", 1999
        for (;;) {
            long current = seedUniquifier.get();
            long next = current * 181783497276652981L;
            if (seedUniquifier.compareAndSet(current, next))
                return next;
        }
    }

初始化原子标志符

private static final AtomicLong seedUniquifier
        = new AtomicLong(8682522807148012L);

使用单个长种子创建一个新的随机数生成器。种子是伪随机数生成器内部状态的初始值,由方法 next 维护。

public Random(long seed) {
        if (getClass() == Random.class)
            this.seed = new AtomicLong(initialScramble(seed));
        else {
            // subclass might have overriden setSeed
            this.seed = new AtomicLong();
            setSeed(seed);
        }
    }

初始化争夺,返回随机数

private static long initialScramble(long seed) {
        return (seed ^ multiplier) & mask;
    }

设置种子

synchronized public void setSeed(long seed) {
        this.seed.set(initialScramble(seed));
        haveNextNextGaussian = false;
    }

生成下一个伪随机数。子类应该覆盖它,因为它被所有其他方法使用。

 protected int next(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * multiplier + addend) & mask;
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

生成随机字节并将它们放入用户提供的字节数组中。产生的随机字节数等于字节数组的长度。

public void nextBytes(byte[] bytes) {
        for (int i = 0, len = bytes.length; i < len; )
            for (int rnd = nextInt(),
                     n = Math.min(len - i, Integer.SIZE/Byte.SIZE);
                 n-- > 0; rnd >>= Byte.SIZE)
                bytes[i++] = (byte)rnd;
    }

LongStream Spliterators 使用的 nextLong 形式。 如果 origin 大于 bound,则作为 nextLong 的无界形式,否则作为有界形式

final long internalNextLong(long origin, long bound) {
        long r = nextLong();
        if (origin < bound) {
            long n = bound - origin, m = n - 1;
            if ((n & m) == 0L)  // power of two
                r = (r & m) + origin;
            else if (n > 0L) {  // reject over-represented candidates
                for (long u = r >>> 1;            // ensure nonnegative
                     u + m - (r = u % n) < 0L;    // rejection check
                     u = nextLong() >>> 1) // retry
                    ;
                r += origin;
            }
            else {              // range not representable as long
                while (r < origin || r >= bound)
                    r = nextLong();
            }
        }
        return r;
    }

IntStream Spliterators 使用的 nextInt 形式。对于无界情况:使用 nextInt()。对于具有可表示范围的有界情况:使用 nextInt(int bound) 对于具有不可表示范围的有界情况:使用 nextInt()

final int internalNextInt(int origin, int bound) {
        if (origin < bound) {
            int n = bound - origin;
            if (n > 0) {
                return nextInt(n) + origin;
            }
            else {  // range not representable as int
                int r;
                do {
                    r = nextInt();
                } while (r < origin || r >= bound);
                return r;
            }
        }
        else {
            return nextInt();
        }
    }

DoubleStream Spliterators 使用的 nextDouble 形式。

 final double internalNextDouble(double origin, double bound) {
        double r = nextDouble();
        if (origin < bound) {
            r = r * (bound - origin) + origin;
            if (r >= bound) // correct for rounding
                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
        }
        return r;
    }

从此随机数生成器的序列返回下一个伪随机、均匀分布的 int 值。 nextInt 的一般约定是伪随机生成并返回一个 int 值。所有 2的32次方 个可能的 int 值都以(大约)相等的概率产生。

public int nextInt() {
        return next(32);
    }

返回一个伪随机、均匀分布的 int 值,介于 0(含)和指定值(不含)之间,从该随机数生成器的序列中提取。 nextInt 的一般约定是伪随机生成并返回指定范围内的一个 int 值。所有绑定可能的 int 值都以(大约)相等的概率产生。

public int nextInt(int bound) {
        if (bound <= 0)
            throw new IllegalArgumentException(BadBound);

        int r = next(31);
        int m = bound - 1;
        if ((bound & m) == 0)  // i.e., bound is a power of 2
            r = (int)((bound * (long)r) >> 31);
        else {
            for (int u = r;
                 u - (r = u % bound) + m < 0;
                 u = next(31))
                ;
        }
        return r;
    }

返回一个伪随机、均匀分布的long 值,介于 0(含)和指定值(不含)之间,从该随机数生成器的序列中提取。 nextIong 的一般约定是伪随机生成并返回指定范围内的一个long 值。所有绑定可能的 long值都以(大约)相等的概率产生。

public long nextLong() {
        // it's okay that the bottom word remains signed.
        return ((long)(next(32)) << 32) + next(32);
    }

随机生成一个布尔值,两个概率相同

public boolean nextBoolean() {
        return next(1) != 0;
    }

返回一个伪随机、均匀分布float数

 public float nextFloat() {
        return next(24) / ((float)(1 << 24));
    }

返回一个伪随机的、均匀分布的double数

public double nextDouble() {
        return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT;
    }

从该随机数生成器的序列返回下一个伪随机、高斯(“正态”)分布的双精度值,平均值为 0.0,标准差为 1.0。

synchronized public double nextGaussian() {
        // See Knuth, ACP, Section 3.4.1 Algorithm C.
        if (haveNextNextGaussian) {
            haveNextNextGaussian = false;
            return nextNextGaussian;
        } else {
            double v1, v2, s;
            do {
                v1 = 2 * nextDouble() - 1; // between -1 and 1
                v2 = 2 * nextDouble() - 1; // between -1 and 1
                s = v1 * v1 + v2 * v2;
            } while (s >= 1 || s == 0);
            double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
            nextNextGaussian = v2 * multiplier;
            haveNextNextGaussian = true;
            return v1 * multiplier;
        }
    }

返回一个流,产生给定的 streamSize 数量的伪随机 int 值。

public IntStream ints(long streamSize) {
        if (streamSize < 0L)
            throw new IllegalArgumentException(BadSize);
        return StreamSupport.intStream
                (new RandomIntsSpliterator
                         (this, 0L, streamSize, Integer.MAX_VALUE, 0),
                 false);
    }

返回一个有效无限的伪随机 int 值流。

public IntStream ints() {
        return StreamSupport.intStream
                (new RandomIntsSpliterator
                         (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
                 false);
    }

返回一个流,产生给定的 streamSize 数量的伪随机 int 值,每个值都符合给定的原点(包含)和边界(不包含)。

public IntStream ints(long streamSize, int randomNumberOrigin,
                          int randomNumberBound) {
        if (streamSize < 0L)
            throw new IllegalArgumentException(BadSize);
        if (randomNumberOrigin >= randomNumberBound)
            throw new IllegalArgumentException(BadRange);
        return StreamSupport.intStream
                (new RandomIntsSpliterator
                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
                 false);
    }

返回一个有效无限的伪随机 int 值流,每个值都符合给定的原点(包含)和边界(不包含)。

public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
        if (randomNumberOrigin >= randomNumberBound)
            throw new IllegalArgumentException(BadRange);
        return StreamSupport.intStream
                (new RandomIntsSpliterator
                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
                 false);
    }

返回一个流,产生给定的 streamSize 数量的伪随机long值。

public LongStream longs(long streamSize) {
        if (streamSize < 0L)
            throw new IllegalArgumentException(BadSize);
        return StreamSupport.longStream
                (new RandomLongsSpliterator
                         (this, 0L, streamSize, Long.MAX_VALUE, 0L),
                 false);
    }

返回一个有效无限的伪随机long值流。

public LongStream longs() {
        return StreamSupport.longStream
                (new RandomLongsSpliterator
                         (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
                 false);
    }

返回一个流,产生给定的 streamSize 数量的伪随机 long,每个都符合给定的原点(包含)和边界(不包含)。

public LongStream longs(long streamSize, long randomNumberOrigin,
                            long randomNumberBound) {
        if (streamSize < 0L)
            throw new IllegalArgumentException(BadSize);
        if (randomNumberOrigin >= randomNumberBound)
            throw new IllegalArgumentException(BadRange);
        return StreamSupport.longStream
                (new RandomLongsSpliterator
                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
                 false);
    }

返回一个有效无限的伪随机long值流,每个值都符合给定的原点(包含)和边界(不包含)

public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
        if (randomNumberOrigin >= randomNumberBound)
            throw new IllegalArgumentException(BadRange);
        return StreamSupport.longStream
                (new RandomLongsSpliterator
                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
                 false);
    }

返回一个流,产生给定的 streamSize 数量的伪随机double值。

public DoubleStream doubles(long streamSize) {
        if (streamSize < 0L)
            throw new IllegalArgumentException(BadSize);
        return StreamSupport.doubleStream
                (new RandomDoublesSpliterator
                         (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
                 false);
    }

返回一个有效无限的伪随机double值流。

public DoubleStream doubles() {
        return StreamSupport.doubleStream
                (new RandomDoublesSpliterator
                         (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
                 false);
    }

返回一个流,产生给定的 streamSize 数量的伪随机double,每个都符合给定的原点(包含)和边界(不包含)。

public DoubleStream doubles(long streamSize, double randomNumberOrigin,
                                double randomNumberBound) {
        if (streamSize < 0L)
            throw new IllegalArgumentException(BadSize);
        if (!(randomNumberOrigin < randomNumberBound))
            throw new IllegalArgumentException(BadRange);
        return StreamSupport.doubleStream
                (new RandomDoublesSpliterator
                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
                 false);
    }

返回一个有效无限的伪随机double值流,每个值都符合给定的原点(包含)和边界(不包含)

public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
        if (!(randomNumberOrigin < randomNumberBound))
            throw new IllegalArgumentException(BadRange);
        return StreamSupport.doubleStream
                (new RandomDoublesSpliterator
                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
                 false);
    }

用于 int 流的 Spliterator。我们将四个 int 版本多路复用为一个类,方法是将小于 origin 的边界视为无界,并将“无限”视为等价于 Long.MAX_VALUE。对于拆分,它使用标准的除以二方法。除了类型之外,此类的 long 和 double 版本是相同的。

static final class RandomIntsSpliterator implements Spliterator.OfInt {
        final Random rng;
        long index;
        final long fence;
        final int origin;
        final int bound;
        RandomIntsSpliterator(Random rng, long index, long fence,
                              int origin, int bound) {
            this.rng = rng; this.index = index; this.fence = fence;
            this.origin = origin; this.bound = bound;
        }

        public RandomIntsSpliterator trySplit() {
            long i = index, m = (i + fence) >>> 1;
            return (m <= i) ? null :
                   new RandomIntsSpliterator(rng, i, index = m, origin, bound);
        }

        public long estimateSize() {
            return fence - index;
        }

        public int characteristics() {
            return (Spliterator.SIZED | Spliterator.SUBSIZED |
                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
        }

        public boolean tryAdvance(IntConsumer consumer) {
            if (consumer == null) throw new NullPointerException();
            long i = index, f = fence;
            if (i < f) {
                consumer.accept(rng.internalNextInt(origin, bound));
                index = i + 1;
                return true;
            }
            return false;
        }

        public void forEachRemaining(IntConsumer consumer) {
            if (consumer == null) throw new NullPointerException();
            long i = index, f = fence;
            if (i < f) {
                index = f;
                Random r = rng;
                int o = origin, b = bound;
                do {
                    consumer.accept(r.internalNextInt(o, b));
                } while (++i < f);
            }
        }
    }

长整型流的分流器

static final class RandomLongsSpliterator implements Spliterator.OfLong {
        final Random rng;
        long index;
        final long fence;
        final long origin;
        final long bound;
        RandomLongsSpliterator(Random rng, long index, long fence,
                               long origin, long bound) {
            this.rng = rng; this.index = index; this.fence = fence;
            this.origin = origin; this.bound = bound;
        }

        public RandomLongsSpliterator trySplit() {
            long i = index, m = (i + fence) >>> 1;
            return (m <= i) ? null :
                   new RandomLongsSpliterator(rng, i, index = m, origin, bound);
        }

        public long estimateSize() {
            return fence - index;
        }

        public int characteristics() {
            return (Spliterator.SIZED | Spliterator.SUBSIZED |
                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
        }

        public boolean tryAdvance(LongConsumer consumer) {
            if (consumer == null) throw new NullPointerException();
            long i = index, f = fence;
            if (i < f) {
                consumer.accept(rng.internalNextLong(origin, bound));
                index = i + 1;
                return true;
            }
            return false;
        }

        public void forEachRemaining(LongConsumer consumer) {
            if (consumer == null) throw new NullPointerException();
            long i = index, f = fence;
            if (i < f) {
                index = f;
                Random r = rng;
                long o = origin, b = bound;
                do {
                    consumer.accept(r.internalNextLong(o, b));
                } while (++i < f);
            }
        }

    }

double流的分流器

static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
        final Random rng;
        long index;
        final long fence;
        final double origin;
        final double bound;
        RandomDoublesSpliterator(Random rng, long index, long fence,
                                 double origin, double bound) {
            this.rng = rng; this.index = index; this.fence = fence;
            this.origin = origin; this.bound = bound;
        }

        public RandomDoublesSpliterator trySplit() {
            long i = index, m = (i + fence) >>> 1;
            return (m <= i) ? null :
                   new RandomDoublesSpliterator(rng, i, index = m, origin, bound);
        }

        public long estimateSize() {
            return fence - index;
        }

        public int characteristics() {
            return (Spliterator.SIZED | Spliterator.SUBSIZED |
                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
        }

        public boolean tryAdvance(DoubleConsumer consumer) {
            if (consumer == null) throw new NullPointerException();
            long i = index, f = fence;
            if (i < f) {
                consumer.accept(rng.internalNextDouble(origin, bound));
                index = i + 1;
                return true;
            }
            return false;
        }

        public void forEachRemaining(DoubleConsumer consumer) {
            if (consumer == null) throw new NullPointerException();
            long i = index, f = fence;
            if (i < f) {
                index = f;
                Random r = rng;
                double o = origin, b = bound;
                do {
                    consumer.accept(r.internalNextDouble(o, b));
                } while (++i < f);
            }
        }
    }

序列化Random函数

private static final ObjectStreamField[] serialPersistentFields = {
        new ObjectStreamField("seed", Long.TYPE),
        new ObjectStreamField("nextNextGaussian", Double.TYPE),
        new ObjectStreamField("haveNextNextGaussian", Boolean.TYPE)
    };

从流中重构 Random 实例(即反序列化它)。

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {

        ObjectInputStream.GetField fields = s.readFields();

        // The seed is read in as {@code long} for
        // historical reasons, but it is converted to an AtomicLong.
        long seedVal = fields.get("seed", -1L);
        if (seedVal < 0)
          throw new java.io.StreamCorruptedException(
                              "Random: invalid seed");
        resetSeed(seedVal);
        nextNextGaussian = fields.get("nextNextGaussian", 0.0);
        haveNextNextGaussian = fields.get("haveNextNextGaussian", false);
    }

将 Random 实例保存到流中。

synchronized private void writeObject(ObjectOutputStream s)
        throws IOException {

        // set the values of the Serializable fields
        ObjectOutputStream.PutField fields = s.putFields();

        // The seed is serialized as a long for historical reasons.
        fields.put("seed", seed.get());
        fields.put("nextNextGaussian", nextNextGaussian);
        fields.put("haveNextNextGaussian", haveNextNextGaussian);

        // save them
        s.writeFields();
    }

支持在反序列化时重置种子

private void resetSeed(long seedVal) {
        unsafe.putObjectVolatile(this, seedOffset, new AtomicLong(seedVal));
    }

Random的静态代码块

static {
        try {
            seedOffset = unsafe.objectFieldOffset
                (Random.class.getDeclaredField("seed"));
        } catch (Exception ex) { throw new Error(ex); }
    }

定义非安全生成种子的语句

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long seedOffset;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绝域时空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值