Java生成随机数的4种方式
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 默认支持两种加密算法:
- SHA1PRNG 算法,提供者 sun.security.provider.SecureRandom;
- 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种方式的更多相关文章
- Java生成随机数的三种方式
package cn.zytao.taosir.random; import java.util.Random; public class RandomDemo { private static In ...
- java产生随机数的几种方式
java产生随机数的几种方式 一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他 ...
- java产生随机数的几种方式(转)
一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他就是个100以内的随机,这个在 ...
- 生成随机数的N种方式
首先需要说明的是,计算机中生成的随机数严格来说都是伪随机,即非真正的随机数,真正随机数的随机样本不可重现.那么我们来看看代码中有哪些方式可以生成随机数. rand rand函数声明如下: #inclu ...
- java产生随机数的三种方式
转自:https://blog.csdn.net/YTTmiao/article/details/78187448 随机数在实际中使用很广泛,比如要随即生成一个固定长度的字符串.数字.或者随即生成一个 ...
- java 获取随机数的三种方法
方法1(数据类型)(最小值+Math.random()*(最大值-最小值+1))例:(int)(1+Math.random()*(10-1+1))从1到10的int型随数 方法2获得随机数for (i ...
- Java获取随机数的几种方法
Java获取随机数的几种方法 .使用org.apache.commons.lang.RandomStringUtils.randomAlphanumeric()取数字字母随机10位; //取得一个3位 ...
- java解析xml的几种方式
java解析xml的几种方式 DOM DOM的全称是Document ObjectModel,也即文档对象模型.在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称D ...
- c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)
c#封装DBHelper类 public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...
随机推荐
- 日常Java 2021/10/6
声明自定义异常 class zidingyiException extends Exception{}//定义自己的异常类 单继承 public class A {} public class B ...
- 学习java 7.12
学习内容: File是文件和目录路径名的抽象表示,File封装的不是一个真正存在的文件,仅仅是一个路径名 File类的方法 绝对目录和相对目录的区别 字节流 使用字节输出流写数据的步骤 : 创建字节输 ...
- A Child's History of England.11
CHAPTER 4 ENGLAND UNDER ATHELSTAN AND THE SIX BOY-KINGS Athelstan, the son of Edward the Elder, succ ...
- python生成器浅析
A 'generator' is a function which returns a generator iterator. It looks like a normal function exce ...
- Docker学习(五)——Docker仓库管理
Docker仓库管理 仓库(Repository)是集中存放镜像的地方. 1.Docker Hub 目前Docker官方维护了一个公共仓库Docker Hub.大部分需求都可以通过 ...
- jenkins的sonarqube之代码检测的两种方法
#:sonarqube下载地址,我们安装6.7 高版本已经不支持MySQL和Mariadb(最小3G内存) https://www.sonarqube.org/downloads/ #:安装文档 h ...
- 3.0 go mod之远程仓库搭建-代码示例
注意事项 所谓的远程仓库指的是github,个人首次使用go mod在其他云仓库上尝试,并未成功,这浪费了我近2小时的时间: 如果你是初次尝试,那么除了github的地址换一下之外,其他的都按照示例操 ...
- 【C/C++】two pointers/归并排序/原理/理解/实现/算法笔记4.6
1.two pointers 思路:对序列进行扫描的时候,根据序列本身的特性用两个下标i和j对序列进行扫描,从而降低算法复杂度. ·例1 在递增序列中找a + b = M while (i<j) ...
- pipeline 结构设计
目录 一.pipeline步骤 二.案例 pipeline详解 只生成一次制品 不同环境部署 系统集成测试 指定版本部署 一.pipeline步骤 当团队开始设计第一个pipeline时,该如何下手呢 ...
- Nginx支持php
目录 一.简介 二.配置 三.测试 四.参数 一.简介 Nginx本身只能解析html文件,但有些网页是php写的,就需要Nginx连接php,将网页解析成html再发给客户端. 配置中将.php 结 ...