Java生成随机数的4种方式,以后就用它了!(6)

ThreadLocalRandom 缺点分析


虽然 ThreadLocalRandom 不支持手动设置随机种子的方法,但并不代表 ThreadLocalRandom 就是完美的,当我们查看 ThreadLocalRandom 初始化随机种子的方法 initialSeed() 源码时发现,默认情况下它的随机种子也是以当前时间有关,源码如下:


private static long initialSeed() {
    // 尝试获取 JVM 的启动参数
    String sec = VM.getSavedProperty("java.util.secureRandomSeed");
    // 如果启动参数设置的值为 true,则参数一个随机 8 位的种子
    if (Boolean.parseBoolean(sec)) {
        byte[] seedBytes = java.security.SecureRandom.getSeed(8);
        long s = (long)(seedBytes[0]) & 0xffL;
        for (int i = 1; i < 8; ++i)
            s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
        return s;
    }
    // 如果没有设置启动参数,则使用当前时间有关的随机种子算法
    return (mix64(System.currentTimeMillis()) ^
            mix64(System.nanoTime()));
}


从上述源码可以看出,当我们设置了启动参数“-Djava.util.secureRandomSeed=true”时,ThreadLocalRandom 会产生一个随机种子,一定程度上能缓解随机种子相同所带来随机数可预测的问题,然而默认情况下如果不设置此参数,那么在多线程中就可以因为启动时间相同,而导致多个线程在每一步操作中都会生成相同的随机数


3.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);
}


以上程序的执行结果为:


Java生成随机数的4种方式,以后就用它了!(6)

上一篇:JS魔法堂:mmDeferred源码剖析


下一篇:MyEclipse 利用反向功能生成Java 实体类