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

    Random

    Random 类诞生于 JDK 1.0,它产生的随机数是伪随机数,也就是有规则的随机数。Random 使用的随机算法为 linear congruential pseudorandom number generator (LGC) 线性同余法伪随机数。在随机数生成时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。

    Random 对象在种子数相同的情况下,相同次数生成的随机数是相同的。比如两个种子数相同的 Random 对象,第一次生成的随机数字完全相同,第二次生成的随机数字也完全相同。默认情况下 new Random() 使用的是当前纳秒时间作为种子数的。

    // 生成 Random 对象

    Random random = new Random();

    for (int i = 0; i < 10; i++) {
    // 生成 0-9 随机整数

    int number = random.nextInt(10);

    System.out.println("生成随机数:" + number);

    }

    优缺点分析

    Random 使用 LGC 算法生成伪随机数的优点是执行效率比较高,生成的速度比较快。

    它的缺点是如果 Random 的随机种子一样的话,每次生成的随机数都是可预测的(都是一样的)。如下代码所示,当我们给两个线程设置相同的种子数的时候,会发现每次产生的随机数也是相同的:

    // 创建两个线程for (int i = 0; i < 2; i++) {

    new Thread(() -> {
    // 创建 Random 对象,设置相同的种子

    Random random = new Random(1024);

    // 生成 3 次随机数

    for (int j = 0; j < 3; j++) {

    // 生成随机数

    int number = random.nextInt();

    // 打印生成的随机数

    System.out.println(Thread.currentThread().getName() + ":" +
    number);
    // 休眠 200 ms

    try {
    Thread.sleep(200);
    } catch (InterruptedException e) {

    e.printStackTrace();
    }
    System.out.println("---------------------");

    }
    }).start();}

    ThreadLocalRandom

    ThreadLocalRandom 是 JDK 1.7 新提供的类,它属于 JUC(java.util.concurrent)下的一员。

    通过 Random 的源码我们可以看出,Random 在生成随机数时使用的 CAS 来解决线程安全问题的,然而 CAS 在线程竞争比较激烈的场景中效率是非常低的,原因是 CAS 对比时老有其他的线程在修改原来的值,所以导致 CAS 对比失败,所以它要一直循环来尝试进行 CAS 操作。所以在多线程竞争比较激烈的场景可以使用 ThreadLocalRandom 来解决 Random 执行效率比较低的问题。

    ThreadLocalRandom 的实现原理与 ThreadLocal 类似,它相当于给每个线程一个自己的本地种子,从而就可以避免因多个线程竞争一个种子,而带来的额外性能开销了。

    // //得到 ThreadLocalRandom 对象

    ThreadLocalRandom random = ThreadLocalRandom.current();

    for (int i = 0; i < 10; i++) {

    // 生成 0-9 随机整数

    int number = random.nextInt(10);

    // 打印结果

    System.out.println("生成随机数:" + number);
    }

    优缺点分析

    ThreadLocalRandom 结合了 Random 和 ThreadLocal 类,并被隔离在当前线程中。因此它通过避免竞争操作种子数,从而在多线程运行的环境中实现了更好的性能,而且也保证了它的线程安全。

    另外,不同于 Random, ThreadLocalRandom 明确不支持设置随机种子。它重写了 Random 的setSeed(long seed) 方法并直接抛出了 UnsupportedOperationException 异常,因此降低了多个线程出现随机数重复的可能性。

     

    SecureRandom

    SecureRandom 继承自 Random,该类提供加密强随机数生成器。SecureRandom 不同于 Random,它收集了一些随机事件,比如鼠标点击,键盘点击等,SecureRandom 使用这些随机事件作为种子。这意味着,种子是不可预测的,而不像 Random 默认使用系统当前时间的毫秒数作为种子,从而避免了生成相同随机数的可能性。
    // 创建 SecureRandom 对象,并设置加密算法

    SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

    for (int i = 0; i < 10; i++) {
    // 生成 0-9 随机整数
    int number = random.nextInt(10);
    // 打印结果
    System.out.println("生成随机数:" + number);}

    SecureRandom 默认支持两种加密算法:

    1. SHA1PRNG 算法,提供者 sun.security.provider.SecureRandom;
    2. NativePRNG 算法,提供者 sun.security.provider.NativePRNG。

    当然除了上述的操作方式之外,你还可以选择使用 new SecureRandom() 来创建 SecureRandom 对象,实现代码如下:

    SecureRandom secureRandom = new SecureRandom();

    通过 new 初始化 SecureRandom,默认会使用 NativePRNG 算法来生成随机数,但是也可以配置 JVM 启动参数“-Djava.security”参数来修改生成随机数的算法,或选择使用 getInstance("算法名称") 的方式来指定生成随机数的算法。

    Math

    Math 类诞生于 JDK 1.0,它里面包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数,当然它里面也包含了生成随机数的静态方法 Math.random() ,此方法会产生一个 0 到 1 的 double 值

    for (int i = 0; i < 10; i++) {  
    // 产生随机数
    double number = Math.random();
    System.out.println("生成随机数:" + number);
    }

    扩展

    当然如果你想用它来生成一个一定范围的 int 值

    for (int i = 0; i < 10; i++) {   
    // 生成一个从 0-99 的整数

    int number = (int) (Math.random() * 100);

    System.out.println("生成随机数:" + number);
    }
     
     
     
  • 相关阅读:
    【打印】windows打印控件,Lodop.js介绍
    【MySQL】MySQL查询数据库各表的行数
    【MySQL】MySQL中查询出数据表中存在重复的值list
    【php】php5.0以上,instanceof 用法
    日期转换:Cannot format given Object as a Date (SimpleDateFormat的parse和format)
    Groovy 正则表达式 匹配点号
    什么是开发框架
    SoapUI 增大使用内存
    Groovy API link
    Groovy 跳出each循环
  • 原文地址:https://www.cnblogs.com/KL2016/p/14897023.html
Copyright © 2011-2022 走看看