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

Java生成随机数的4种方式的更多相关文章

  1. Java生成随机数的三种方式

    package cn.zytao.taosir.random; import java.util.Random; public class RandomDemo { private static In ...

  2. java产生随机数的几种方式

    java产生随机数的几种方式 一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他 ...

  3. java产生随机数的几种方式(转)

    一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他就是个100以内的随机,这个在 ...

  4. 生成随机数的N种方式

    首先需要说明的是,计算机中生成的随机数严格来说都是伪随机,即非真正的随机数,真正随机数的随机样本不可重现.那么我们来看看代码中有哪些方式可以生成随机数. rand rand函数声明如下: #inclu ...

  5. java产生随机数的三种方式

    转自:https://blog.csdn.net/YTTmiao/article/details/78187448 随机数在实际中使用很广泛,比如要随即生成一个固定长度的字符串.数字.或者随即生成一个 ...

  6. java 获取随机数的三种方法

    方法1(数据类型)(最小值+Math.random()*(最大值-最小值+1))例:(int)(1+Math.random()*(10-1+1))从1到10的int型随数 方法2获得随机数for (i ...

  7. Java获取随机数的几种方法

    Java获取随机数的几种方法 .使用org.apache.commons.lang.RandomStringUtils.randomAlphanumeric()取数字字母随机10位; //取得一个3位 ...

  8. java解析xml的几种方式

    java解析xml的几种方式 DOM DOM的全称是Document ObjectModel,也即文档对象模型.在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称D ...

  9. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

随机推荐

  1. 数据库之JDBC

    1.简单认识一下JDBC 1).JDBC是什么? java database connection       java数据库连接 作用:就是为了java连接mysql数据库嘛 要详细的,就面向百度编 ...

  2. 疯了吧!这帮人居然用 Go 写“前端”?(一)

    作者 | 郑嘉涛(羣青) 来源 | 尔达 Erda 公众号 ​ 无一例外,谈到前后端分离"必定"是 RESTful API,算是定式了.但我们知道 REST 在资源划分上的设计总是 ...

  3. 【区间dp】- P1880 [NOI1995] 石子合并

    记录一下第一道ac的区间dp 题目:P1880 [NOI1995] 石子合并 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码: #include <iostream> ...

  4. Give You My Best Wishes

    亲耐滴IT童鞋们: 感谢大家一直以来的支持,因为有你们的支持,才有我这么"拼"的动力!!爱你们哟 OC的学习已经告一段落,希望大家通过阅读这几篇浅薄的随笔,能够寻找到解决问题的方法 ...

  5. java对象分配

    1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我 ...

  6. SVN的基本介绍\服务器配置

    ### 1. 工作场景 1. 进入公司需要做的关于开发的第一件事, 就是向项目经理索要SVN服务器地址+用户名+密码### 2. 角色解释> 服务器: 用于存放所有版本的代码,供客户端上传下载更 ...

  7. 【Linux】【Commands】基础概念及常用基础命令

    命令的语法通用格式: ------------------------------------------------ #COMMAND OPTIONS ARGUMENTS 发起命令:请求内核将某个二 ...

  8. .Net Core MVC全局过滤器验证是否需要登录

    1.新增全局登录过滤器LoginCheckAttribute 1 public class LoginCheckAttribute: ActionFilterAttribute 2 { 3 publi ...

  9. ES6解构赋值的简单使用

    相较于常规的赋值方式,解构赋值最主要的是'解构'两个字,在赋值的过程中要清晰的知道等号右边的结构. 先简单地看一下原来的赋值方式. var a=[1,2] 分析一下这句代码的几个点: (1)变量申明和 ...

  10. Charles ios设备抓包

    在Mac下做开发,用Fiddler抓包由于离不开Windows比较痛苦,还好有Charles,到官网http://www.charlesproxy.com/可下载到最新版本(若不支持rMBP可拖到Re ...