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面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》