赞
踩
产生的随机数是 [0,1) 之间的一个 double,即 0 <= random < 1。
当第一次调用 Math.random() 方法时,自动创建了一个伪随机数生成器,实际上用的是 new java.util.Random()。当接下来继续调用 Math.random() 方法时,就会使用这个新的伪随机数生成器。
public static double random() {
return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
private static final class RandomNumberGeneratorHolder {
static final Random randomNumberGenerator = new Random();
}
在多线程情况下,只有一个线程会负责创建伪随机数生成器(使用当前时间作为种子),其他线程则利用该伪随机数生成器产生随机数。因此 Math.random() 方法是线程安全的。
在java.util这个包里面提供了一个Random的类,我们可以新建一个Random的对象来产生随机数,他可以产生随机整数、随机float、随机double,随机long,这个也是我们在j2me的程序里经常用的一个取随机数的方法。
基本算法:
linear congruential pseudorandom number generator (LGC) 线性同余法伪随机数生成器
缺点:
可预测。从输出中可以很容易计算出种子值。因此可以预测出下一个输出的随机数。
在注重信息安全的应用中,不要使用 LCG 算法生成随机数,请使用 SecureRandom。
Random类提供的方法:API
java.util.Random类有两种方式构建方式:
只要种子一样,产生的随机数也一样: 因为种子确定,随机数算法也确定,因此输出是确定的。
不带参数的 ints方法将返回一个无限 int 流:
IntStream unlimitedIntStream = random.ints();
调用时还可以指定参数来限制流大小:
IntStream limitedIntStream = random.ints(streamSize);
当然,也可以为生成数值设置最大值和最小值:
IntStream limitedIntStreamWithinARange = random.ints(streamSize, min, max);
ThreadLocalRandom 是 JDK 7 之后提供,也是继承至 java.util.Random。
每一个线程有一个独立的随机数生成器,用于并发产生随机数,能够解决多个线程发生的竞争争夺。效率更高!
ThreadLocalRandom 不是直接用 new 实例化,而是第一次使用其静态方法 current() 得到ThreadLocal 实例,然后调用 java.util.Random 类提供的方法获得各种随机数。
public class JavaRandom {
public static void main(String args[]) {
new MyThread().start();
new MyThread().start();
}
}
class MyThread extends Thread {
public void run() {
for (int i = 0; i < 2; i++) {
System.out.println(Thread.currentThread().getName() + ": " + ThreadLocalRandom.current().nextDouble());
}
}
}
Java 8 还带来了一个快速随机数生成器SplittableRandom类。
正如 JavaDoc 中描述的那样,这是一个支持并行计算的随机数生成器。值得注意的是,这个实例非线程安全。使用该类时需要当心。
现在有了 nextInt 和 ints 方法。调用 nextInt 时,可以通过参数指定 top 和 bottom 范围:
SplittableRandom splittableRandom = new SplittableRandom();
int randomWithSplittableRandom = splittableRandom.nextInt(min, max);
这里也提供了ints方法。这意味着可以轻松得到 int流。
此类提供强加密生成器(RNG),也是继承至 java.util.Random。操作系统收集了一些随机事件,比如鼠标点击,键盘点击等等,SecureRandom 使用这些随机事件作为种子。
强加密:
根据rfc 1750 描述:任何传递给secureRandom对象的种子材料必须是不可预知的,所有SecureRandom对象输出的输出序列必须是强加密的。
对象获取:
可通过无参构造或getInstance()方法获得对象
方法:
支持的随机算法只有一个: SHA1PRNG
使用:
SecureRandom random1 = SecureRandom.getInstance("SHA1PRNG");
SecureRandom random2 = SecureRandom.getInstance("SHA1PRNG");
for (int i = 0; i < 5; i++) {
System.out.println(random1.nextInt() + " != " + random2.nextInt());
}
可以使用 Apache Commons-Lang 包中的 RandomStringUtils 类。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。