zoukankan      html  css  js  c++  java
  • java生成随机数的三种方式

    1、java.util.Random()

      伪随机,如果不传入种子,以当前系统时间为种子,通过一系列计算得出随机值,种子相同的情况下,每次调用得到的随机值是固定的

    2、Math.random()  

        public static double random() {
            return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
        }
        private static final class RandomNumberGeneratorHolder {
            static final Random randomNumberGenerator = new Random();
        }

      Math内部也是通过java.util.Random()实现的

    3、java.security.SecureRandom()

      new SecureRandom();
      SecureRandom.getInstance("");
      SecureRandom.getInstanceStrong();

      可以使用以上三种方式生成对象,推荐使用new SecureRandom(),使用系统默认的算法并由系统生成种子

      SecureRandom继承于Random类,其具体的实现类为SecureRandomSpi,与平台相关,以JDK版本jdk-8u251-linux-x64为例,在Linux系统下,其默认的实现类为NativePRNG,随机源为/dev/random以及/dev/urandom

      /dev/random和/dev/urandom是Linux系统中提供的随机伪设备,使用这两个设备可以为应用提供不为空的随机字节流,两者的区别是/dev/random在系统噪声不足时,会产生阻塞,而/dev/urandom是/dev/random的一个副本,它会重复使用熵池中的数据以产生伪随机数据,因此不会有阻塞的问题

      NativePRNG基于混合模式,为生成随机数与随机种子提供了不同的支持

                    case MIXED:
                        File var4 = null;
                        URL var3;
                        if ((var3 = NativePRNG.getEgdUrl()) != null) {
                            try {
                                var4 = SunEntries.getDeviceFile(var3);
                            } catch (IOException var7) {
                                ;
                            }
                        }
    
                        if (var4 != null && var4.canRead()) {
                            var1 = var4;
                        } else {
                            var1 = new File("/dev/random");
                        }
    
                        var2 = new File("/dev/urandom");
                        break;

      对于随机数的生成,NativePRNG总是使用/dev/urandom作为随机源,而对于种子的生成,其随机源则取决于配置。在NativePRNG.getEgdUrl()方法中,程序会读取配置java.security.egd以及securerandom.source配置

      比如配置-Djava.security.egd=file:/dev/urandom,则采用非阻塞模式,而如果配置-Djava.security.egd=file:/dev/urandom,则采用阻塞模式,系统默认也是采用阻塞模式生成种子,以保证足够的随机性

        private static final String seedSource = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {
            public String run() {
                String var1 = System.getProperty("java.security.egd", "");
                if (var1.length() != 0) {
                    return var1;
                } else {
                    var1 = Security.getProperty("securerandom.source");
                    return var1 == null ? "" : var1;
                }
            }
        });

      需要注意的是,SecureRandom.getInstanceStrong()方法,并不遵从上述方式,而是读取配置securerandom.strongAlgorithms,并以此构建随机生成器,在Linux系统下,该配置默认为NativePRNGBlocking:SUN,即采用NativePRNG.Blocking类作为其实现,该方法与SecureRandom.getInstance("NativePRNGBlocking","SUN")语义相同

                    case BLOCKING:
                        var1 = new File("/dev/random");
                        var2 = new File("/dev/random");
                        break;

      由代码可知,getInstanceStrong()返回的随机生成器,对于生成随机种子以及随机数都是访问/dev/random,这个方法性能上是非常差的,没有特殊需求,不推荐使用

      

  • 相关阅读:
    [LeetCode] 310. Minimum Height Trees
    [LeetCode] 722. Remove Comments
    [LeetCode] 243, 244, 245. Shortest Word Distance I, II, III
    [LeetCode] 939. Minimum Area Rectangle
    [LeetCode] 135. Candy
    [LeetCode] 1395. Count Number of Teams
    [LeetCode] 673. Number of Longest Increasing Subsequence
    [LeetCode] 724. Find Pivot Index
    [LeetCode] 1219. Path with Maximum Gold
    [LeetCode] 849. Maximize Distance to Closest Person
  • 原文地址:https://www.cnblogs.com/yytxdy/p/12845248.html
Copyright © 2011-2022 走看看