Java随机数生成详解(4种常见生成方式)

Java随机数生成详解(4种常见生成方式)-mikechen

Java随机数生成也是Java程序员经常编程使用到的,下面我就重点详解4种常见的Java随机数生成@mikechen

第一种:new Random()

第一种需要借助java.util.Random类来产生一个随机数发生器,也是最常用的一种。

1.Random简介

Random是随机的意思 ,Random类是java.until下,Random 类提供了丰富的随机数生成方法。

Random可以产生 boolean、int、long、float、byte 数组,以及 double 类型等的随机数。

 

2.Random算法

Random 使用的随机算法为 linear congruential pseudorandom number generator (LGC) 线性同余法伪随机数。

随机算法的起源数字被成为种子数(seed),虽然Random类产生的数字是随机的,但在相同种子数(seed)下的相同次数产生的随机数是相同的(伪随机)。

 

3.Random对象生成

Random对象的生成,Random中共有两种构造方法:

1)  public Random()

此构造方法是以系统自身的时间为种子数来构造Random对象。

2)public Random(long seed)

此构造方法可以自己来选定具体的种子来构造Random对象。

 

4.Random示例

下面举几个比较常见的生成随机数例子:

//创建Random对象
Random r=new Random();

int i1 = r.nextInt();//生成一个随机整型值

int i2=r.nextInt(10);// // 生成[0,10)区间的整数

int i3= r.nextInt(18) - 5; // 生成[-5,15)区间的整数

double d1 = r.nextDouble(); // 生成[0,1.0)区间的小数

double d2 = r.nextDouble() * 7; // 生成[0,7.0)区间的小数

long l1 = r.nextLong(); // 生成一个随机长整型值
   
boolean b1 = r.nextBoolean(); // 生成一个随机布尔型值

 

5.Random优缺点分析

优点:

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

缺点:

它的缺点是如果 Random 的随机种子一样的话,每次生成的随机数都是可预测的(都是一样的)。

 

第二种:Math.random()

使用Math.random()方法可以生成[0,1]区间中double类型的数字。

不同于Random的地方在于:Math.random()方法:它只能产生 double 类型的 0~1 的随机数。

若是我们想使用Math.random()方法生成int类型的随机数,可以利用强制类型转换即可。

具体示例如下:

int i1 = (int) (Math.random() * 10);//随机生成[0,10)之间的整数

// 产生一个-2~100的数
int min = -2; // 定义随机数的最小值
int max = 100; // 定义随机数的最大值
int i2 = (int) min + (int) (Math.random() * (max - min));//[-2,100)

 

第三种:SecureRandom()

SecureRandom是强随机数生成器,主要应用的场景为用于安全目的的数据数,例如:生成秘钥或者会话标示(session ID)等。

我们知道Random类中实现的随机算法是伪随机,在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。

相同种子数的Random对象,相同次数生成的随机数字是完全相同的,也就是说,两个种子数相同的Random对象,生成的随机数字完全相同。

所以在需要频繁生成随机数,或者安全要求较高的时候,不要使用Random,因为其生成的值其实是可以预测的,这就是SecureRandom的价值,更安全。

具体示例如下:

SecureRandom random = new SecureRandom();
String returnValue = "";
int randomInt = 0;
int range = 9;
for(int i=0; i<5; i++ ){
    randomInt = random.nextInt(range+1);
    returnValue = returnValue + randomInt;
}
 
System.out.println(returnValue);

1) range :是代表随机生成数的最大值;

2) random.nextInt(range+1) :获取指定范围的随机数,比如 在上面的代码中range=9,说明生成的随机数在0~8中产生。

因为nextInt(a)中a的取值是[0,a) ,是从0开始的,所以上面代码中才要把range+1。

 

第四种:ThreadLocalRandom

ThreadLocalRandom 是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。

Random 在生成随机数时使用的 CAS 来解决线程安全问题的,然而 CAS 在线程竞争比较激烈的场景中效率是非常低的,原因是 CAS 对比时老有其他的线程在修改原来的值。

所以导致 CAS 对比失败,所以它要一直循环来尝试进行 CAS 操作,所以在多线程竞争比较激烈的场景可以使用 ThreadLocalRandom 来解决 Random 执行效率比较低的问题。

具体示例如下:

public static void main(String[] args) {
    ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
    for (int i = 0; i < 10; i++) {
        //(1)获取5以内的随机数
        System.out.println(threadLocalRandom.nextInt(5));
    }
}

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法