Java随机数
本章先讲解Java随机数的几种产生方式,然后通过示例对其进行演示。
广义上讲,Java中的随机数的有三种产生方式:
(01). 通过System.currentTimeMillis()来获取一个当前时间毫秒数的long型数字。
(02). 通过Math.random()返回一个0到1之间的double值。
(03). 通过Random类来产生一个随机数,这个是专业的Random工具类,功能强大。
第1种
通过System.currentTimeMillis()来获取随机数。实际上是获取当前时间毫秒数,它是long类型。使用方法如下:
final long l = System.currentTimeMillis();
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0, 100)之间的int整数。方法如下:
final long l = System.currentTimeMillis();
final int i = (int)( l % 100 );
第2种
通过Math.random()来获取随机数。实际上,它返回的是0(包含)到1(不包含)之间的double值。使用方法如下:
final double d = Math.random();
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0, 100)之间的int整数。方法如下:
final double d = Math.random();
final int i = (int)(d*100);
Math.random();方法执行的本质是调用Random.nextDouble()方法;这里来看一个Math.random()的源码:
private static Random randomNumberGenerator; //定义一个Random的私有的静态的变量
// 对Random进行初始化操作
private static synchronized Random initRNG() {
Random rnd = randomNumberGenerator;
return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd;
}
public static double random() {
Random rnd = randomNumberGenerator;
if (rnd == null) rnd = initRNG();
return rnd.nextDouble();
}
对上述源码进行简单解析:首先定义一个private static 的Random变量,这样所有的Math对象都可以共享这个类变量,而且只用初始化一次就可以,
执行random()方法的时候,首先判断类random变量是否已经被赋值,如果为null,则进行初始化操作,(初始化过程用Synchronized进行同步,适用于多线程环境);
如果对象不为null,说明已经完成了初始化操作,那么直接调用random的nextDouble()方法。
如果只涉及到单线程的话,这个操作等价于Random random = new Random(); return random.nextDouble();
第3种
通过Random类来获取随机数。
使用方法如下:
(01) 创建Random对象。有两种方法可以创建Random对象,如下:
Random random = new Random();//默认构造方法
Random random = new Random(1000);//指定种子数字
(02) 通过Random对象获取随机数。Random支持的随机值类型包括:boolean, byte, int, long, float, double。
比如,获取[0, 100)之间的int整数。方法如下:
int i2 = random.nextInt(100);
Random 的函数接口

// 构造函数(一): 创建一个新的随机数生成器。
Random()
// 构造函数(二): 使用单个 long 种子创建一个新随机数生成器: public Random(long seed) { setSeed(seed); } next 方法使用它来保存随机数生成器的状态。
Random(long seed) boolean nextBoolean() // 返回下一个“boolean类型”伪随机数。
void nextBytes(byte[] buf) // 生成随机字节并将其置于字节数组buf中。
double nextDouble() // 返回一个“[0.0, 1.0) 之间的double类型”的随机数。
float nextFloat() // 返回一个“[0.0, 1.0) 之间的float类型”的随机数。
int nextInt() // 返回下一个“int类型”随机数。
int nextInt(int n) // 返回一个“[0, n) 之间的int类型”的随机数。
long nextLong() // 返回下一个“long类型”随机数。
synchronized double nextGaussian() // 返回下一个“double类型”的随机数,它是呈高斯(“正常地”)分布的 double 值,其平均值是 0.0,标准偏差是 1.0。
synchronized void setSeed(long seed) // 使用单个 long 种子设置此随机数生成器的种子。

接口源码实现:
//最基本的方法,所有的随机数生成方法都调用了他,同时可以看到,Random采用的种子是AtomicLong类型的原子类,next方法来进行求解的时候使用了CAS机制保证了操作的原子类与线程安全性
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
} //nextInt()调用了next(32)方法
public int nextInt() {
return next(32);
}
//nextInt(n)调用了next(31)方法,然后对n取余,这样就可以求得[0,n)之内的随机数了
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive"); if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31); int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
}
//调用了next(32),然后左移32位,在加上next(32)
public long nextLong() {
// it's okay that the bottom word remains signed.
return ((long)(next(32)) << 32) + next(32);
}
//调用了next(1),判断结果是否是0来生成true还是false
public boolean nextBoolean() {
return next(1) != 0;
}
//调用了next(24)
public float nextFloat() {
return next(24) / ((float)(1 << 24));
}
//调用了next(26)与next(27)
public double nextDouble() {
return (((long)(next(26)) << 27) + next(27))
/ (double)(1L << 53);
}
note:Random是线程安全的,用AtomicLong原子类以及CAS机制保证了操作的原子性,在进行种子设置的时候采用synchronized保证了操作的同步性,
但是多线程环境中,不建议采用Random方法,影响性能,建议采用java.util.concurrent.ThreadLocalRandom类,如果强调加密的安全性,
建议使用java.security.SecureRandom.
获取随机数示例
下面通过示例演示上面3种获取随机数的使用方法。
源码如下(RandomTest.java):

1 import java.util.Random;
2 import java.lang.Math;
3
4 /**
5 * java 的随机数测试程序。共3种获取随机数的方法:
6 * (01)、通过System.currentTimeMillis()来获取一个当前时间毫秒数的long型数字。
7 * (02)、通过Math.random()返回一个0到1之间的double值。
8 * (03)、通过Random类来产生一个随机数,这个是专业的Random工具类,功能强大。
9 *
10 * @author skywang
11 * @email kuiwu-wang@163.com
12 */
13 public class RandomTest{
14
15 public static void main(String args[]){
16
17 // 通过System的currentTimeMillis()返回随机数
18 testSystemTimeMillis();
19
20 // 通过Math的random()返回随机数
21 testMathRandom();
22
23 // 新建“种子为1000”的Random对象,并通过该种子去测试Random的API
24 testRandomAPIs(new Random(1000), " 1st Random(1000)");
25 testRandomAPIs(new Random(1000), " 2nd Random(1000)");
26 // 新建“默认种子”的Random对象,并通过该种子去测试Random的API
27 testRandomAPIs(new Random(), " 1st Random()");
28 testRandomAPIs(new Random(), " 2nd Random()");
29 }
30
31 /**
32 * 返回随机数-01:测试System的currentTimeMillis()
33 */
34 private static void testSystemTimeMillis() {
35 // 通过
36 final long l = System.currentTimeMillis();
37 // 通过l获取一个[0, 100)之间的整数
38 final int i = (int)( l % 100 );
39
40 System.out.printf("\n---- System.currentTimeMillis() ----\n l=%s i=%s\n", l, i);
41 }
42
43
44 /**
45 * 返回随机数-02:测试Math的random()
46 */
47 private static void testMathRandom() {
48 // 通过Math的random()函数返回一个double类型随机数,范围[0.0, 1.0)
49 final double d = Math.random();
50 // 通过d获取一个[0, 100)之间的整数
51 final int i = (int)(d*100);
52
53 System.out.printf("\n---- Math.random() ----\n d=%s i=%s\n", d, i);
54 }
55
56
57 /**
58 * 返回随机数-03:测试Random的API
59 */
60 private static void testRandomAPIs(Random random, String title) {
61 final int BUFFER_LEN = 5;
62
63 // 获取随机的boolean值
64 boolean b = random.nextBoolean();
65 // 获取随机的数组buf[]
66 byte[] buf = new byte[BUFFER_LEN];
67 random.nextBytes(buf);
68 // 获取随机的Double值,范围[0.0, 1.0)
69 double d = random.nextDouble();
70 // 获取随机的float值,范围[0.0, 1.0)
71 float f = random.nextFloat();
72 // 获取随机的int值
73 int i1 = random.nextInt();
74 // 获取随机的[0,100)之间的int值
75 int i2 = random.nextInt(100);
76 // 获取随机的高斯分布的double值
77 double g = random.nextGaussian();
78 // 获取随机的long值
79 long l = random.nextLong();
80
81 System.out.printf("\n---- %s ----\nb=%s, d=%s, f=%s, i1=%s, i2=%s, g=%s, l=%s, buf=[",
82 title, b, d, f, i1, i2, g, l);
83 for (byte bt:buf)
84 System.out.printf("%s, ", bt);
85 System.out.println("]");
86 }
87 }

Java随机数的更多相关文章
- Java 随机数
本章先讲解Java随机数的几种产生方式,然后通过示例对其进行演示. 广义上讲,Java中的随机数的有三种产生方式:(01). 通过System.currentTimeMillis()来获取一个当前时间 ...
- 学习记录 java随机数的产生机制
java 随机数 一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他就是个100 ...
- java随机数与数组的使用。
java随机数与数组的使用. 一:题目 二 代码: public class Students { int number; // 学号 int State ; // 年级 ...
- Java随机数和UUID
Java随机数和UUID Java随机数 在Java项目中通常是通过Math.random方法和Random类来获得随机数,前者通过生成一个Random类的实例来实现. 此类产生的是一组伪随机数流,通 ...
- java 随机数高效生成
分享牛,分享牛原创.近期去面试经常被问到java如何生产随机数,以及生成很大的字符串保证不能重复,还要考虑性能,之前本人面试别人的时候,可能不会问这个问题.既然这个java随机数问题经常被问到,那咱们 ...
- (转)Java随机数
1 随机数的三种产生方式 本章先讲解Java随机数的几种产生方式,然后通过示例对其进行演示. 广义上讲,Java中的随机数的有三种产生方式: (01). 通过System.currentTimeMil ...
- java 随机数 <%=System.currentTimeMillis() %>
java 随机数<c:set var="version" value="<%=System.currentTimeMillis() %>"/& ...
- 硬核 - Java 随机数相关 API 的演进与思考(上)
本系列将 Java 17 之前的随机数 API 以及 Java 17 之后的统一 API 都做了比较详细的说明,并且将随机数的特性以及实现思路也做了一些简单的分析,帮助大家明白为何会有这么多的随机数算 ...
- 硬核 - Java 随机数相关 API 的演进与思考(下)
本系列将 Java 17 之前的随机数 API 以及 Java 17 之后的统一 API 都做了比较详细的说明,并且将随机数的特性以及实现思路也做了一些简单的分析,帮助大家明白为何会有这么多的随机数算 ...
随机推荐
- Obj2002java
计算球体积 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- NDK开发之字符串操作
在JNI中,Java字符串被当作一个引用来处理.这些引用类型并不像原生C字符串一样可以直接使用,JNI提供了Java字符串与C字符串之间转换的必要函数,因为Java字符串对象是不可变的(如果对这里有异 ...
- idea集成svn插件
1.需要在机器上安装一个SVN客户端命令行程序,可以到这里下载对应的安装程序:http://subversion.apache.org/packages.html#windows 我选择的是torto ...
- Ubuntu安装gevent
今天在安装包的过程中,按照网上的文章,出错,找了很久,最后才安装成功,希望能解决以后大家遇到的问题 Ubuntu安装gevent Gevent是一个基于greenlet的Python的并发框架,以赖于 ...
- PHP 根据值查找键名
array_search (PHP 4 >= 4.0.5, PHP 5) mixed array_search ( mixed $needle , array $haystack [, bool ...
- IIS配置不正确可能导致“远程服务器返回错误: (404) 未找到"错误一例。
今天上传附件出现了下图所示的问题: 查找百度发现http://www.cnblogs.com/chuncn/archive/2009/09/08/1562759.html 文中提的比较靠谱. 但是,设 ...
- 学习java随笔第九篇:java异常处理
在java中的异常处理和c#中的异常处理是一样的都是用try-catch语句. 基本语法如下 try { //此处是可能出现异常的代码 } catch(Exception e) { //此处是如果发生 ...
- 优化有标量子查询的SQL
数据库环境:SQL SERVER 2008R2 今天在数据库中抓出一条比较耗费资源的SQL,只返回904条数据,居然跑了40多分钟.SQL及对应的数据量如下图: SELECT saft04.cur_y ...
- Java文件操作二:File文件的方法
一.文件的判断方法 判断方法 .boolean canExecute()判断文件是否可执行 .boolean canRead()判断文件是否可读 .boolean canWrite() 判断文件是否可 ...
- iOS 使用GBK编码的hmacMD5算法
该方法是写在工具类中的,而不是写在NSString的类别中 方法的声明: /** * 使用hmac-md5加密 * * @param clearText 原文 * @param secret ...