Java--生成随机数(Math.random() 方法、Random类、ThreadLocalRandom类、SecureRandom类)


一、Math类的random() 方法

只能产生 double 类型的 0~1 (包含0,不包含1)的随机数。

//产生一个min~max内的随机数。
int r = (int)min + (int)(Math.random() * (max - min));

二、Random 类

Random 类位于 java.util 包中。

使用前先创建对象:Random r = new Random();

种子数:在随机数生成时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。

使用的随机算法为线性同余法伪随机数(LGC算法
 
优点
 
提供了丰富的随机数生成方法,可以产生 boolean、int、long、float、byte 数组以及 double 类型的随机数
 
执行效率较高,生成速度较快。
 
缺点
 
产生的随机数是伪随机数,即 有规律的随机数。
 
对象在种子数相同的情况下,相同次数生成的随机数是相同的。

Random常用的两个构造方法:
 
1)Random():该构造方法使用当前系统纳秒时间作为种子数,然后使用这个种子数构造 Random 对象。
 
2)Random(long seed):使用单个 long 类型的参数创建一个新的随机数生成器。

Random类的常用方法

Random是线程安全的。

线程安全 指的是在多线程的场景下,程序的执行结果和预期的结果一致,就叫线程安全的,否则则为非线程安全的(也叫线程安全问题)。比如有两个线程,第一个线程执行 10 万次 ++ 操作,第二个线程执行 10 万次 – 操作,那么最终的结果应该是没加也没减,如果程序最终的结果和预期不符,则为非线程安全的。


三、ThreadLocalRandom类

使用前先创建 ThreadLocalRandom 对象:
 
ThreadLocalRandom random = ThreadLocalRandom.current();

优点
 
1)ThreadLocalRandom 结合了 Random 和 ThreadLocal 类,并被隔离在当前线程中。因此它通过避免竞争操作种子数,从而在多线程运行的环境中实现了更好的性能,而且也保证了它的线程安全。
 
2)另外,不同于 Random, ThreadLocalRandom 明确不支持设置随机种子。它重写了 Random 的
setSeed(long seed) 方法并直接抛出了 UnsupportedOperationException 异常,因此降低了多个线程出现随机数重复的可能性。

缺点
 
默认情况下它的随机种子也是以当前时间有关。
 
即默认情况下如果不设置此参数,那么在多线程中就可以因为启动时间相同,而导致多个线程在每一步操作中都会生成相同的随机数。

示例

//SecureRandom类的示例是仅将下面这一步改成:
// 创建 SecureRandom 对象,并设置加密算法
//SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

// 得到 ThreadLocalRandom 对象
ThreadLocalRandom random = ThreadLocalRandom.current();

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

四、SecureRandom类

使用前先创建 SecureRandom 对象,并设置加密算法:
 
SecureRandom 默认支持两种加密算法:SHA1PRNG 算法 和 NativePRNG 算法。
 
① SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
 
② SecureRandom random = SecureRandom.getInstance("NativePRNG");
 
或使用new SecureRandom()来创建 SecureRandom 对象:
 
③SecureRandom secureRandom = new SecureRandom();
 
此时默认会使用 NativePRNG 算法来生成随机数。

SecureRandom 与 Random
 
1)SecureRandom 继承自 Random,该类提供加密强随机数生成器。
 
2)SecureRandom 不同于 Random,它收集了一些随机事件,比如鼠标点击,键盘点击等,SecureRandom 使用这些随机事件作为种子。即种子是不可预测的,而不像 Random 默认使用系统当前时间的毫秒数作为种子,从而避免了生成相同随机数的可能性。


五、总结

1) Math 是对 Random 的封装,两者类似。
 
2)Random 生成的是伪随机数,是以当前纳秒时间作为种子数的。
 
在多线程竞争比较激烈时,要进行 CAS 操作,存在一定性能问题
 
但对于绝大数应用场景来说,使用 Random 足够了。
 
3)多线程竞争较激烈时:使用 ThreadLocalRandom 替代 Random
 
4)对安全性要求较高时:使用 SecureRandom
 
因为 SecureRandom 会收集一些随机事件来作为随机种子,可看作是生成真正随机数的一个工具类。


参考:

C语言中文网 Java生成随机数(random()和Random类)

云+社区-腾讯云 Java生成随机数的4种方式!(⭐)

猜你喜欢

转载自blog.csdn.net/xiaoyu_alive/article/details/123322334