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 都做了比较详细的说明,并且将随机数的特性以及实现思路也做了一些简单的分析,帮助大家明白为何会有这么多的随机数算 ...
随机推荐
- 训练趣题:黑与白 有A、B、C、D、E五人,每人额头上都帖了一张黑或白的纸。(此处用javascript实现)
今天的题目原题是这样的: “ 黑与白:有A.B.C.D.E五人,每人额头上都帖了一张黑或白的纸.五人对坐,每人都可以看到其它人额头上的纸的颜色.五人相互观察后,A说:“我看见有三人额头上帖的是白纸,一 ...
- site与subsite
1.List template只能加载在主站点上,加载在主站点上之后,其subsite也能引用: 2.发布webpart的时候,路径也只能写网站集的路径,发布到网站集之后其主站点和subsite都能引 ...
- [Excel] CsvHelper---C#关于CSV文件的导入和导出以及转化 (转载)
点击下载 CsvHelper.rar 这个类是关于Csv文件的一些高级操作1.DataTable导出到CSV2.将Csv读入DataTable看下面代码吧 /// <summary> // ...
- 《你不常用的c#之四》:Array的小抽屉ArraySegment
转载自csdn:http://blog.csdn.net/robingaoxb/article/details/6200060 一:)略谈 ArraySegment顾名思义就是Array区块 ...
- Android占位符
<xliff:g>标签介绍: 属性id可以随便命名 属性值举例说明%n$ms:代表输出的是字符串,n代表是第几个参数,设置m的值可以在输出之前放置空格 %n$md:代表输出的是整数,n代表 ...
- 如何获得Windows 8中已记住的WIFI的明文密码
网上很流行的一种查看WIFI密码明文的方法,如下: 今天遇到了一种状况,就是如果不连WIFI的情况我能抓到这个密码吗?(实在不想开口问同事密码多少,只能苦逼的自己想办法了o(︶︿︶)o ) 答案当然是 ...
- Oralce9 的新方法: Merge into Using
一.语义 MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句.通过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,连接条件匹配上的进行UPDATE,无 ...
- ios 设置label的高度随着内容的变化而变化
好吧 步骤1:创建label _GeRenJianJie = [[UILabel alloc]init]; 步骤2:设置label _GeRenJianJie.textColor = RGBAColo ...
- CSS Margin(外边距)
CSS Margin(外边距)属性定义元素周围的空间. Margin margin清除周围的元素(外边框)的区域.margin没有背景颜色,是完全透明的 margin可以单独改变元素的上,下,左,右边 ...
- ACM hdu 1019 Least Common Multiple
Problem Description The least common multiple (LCM) of a set of positive integers is the smallest po ...