java中常用的三个随机数类:
Random 是最常用的类,ThreadLocalRandom 性能快,SecureRandom 注重安全。 下面简单分析3个类的使用。
伪随机数生成器,可以传一个种子来生成随机数。
种子就是一个指定的变量,用来参与生成随机数,如果什么都不传,默认使用System.nanoTime()
来参与生成。
特点:Random
是线程安全的、不是加密安全的,因为是伪随机数。
Random
用到了compareAndSet + synchronized来解决线程安全问题,虽然可以使用ThreadLocal<Random>
来避免竞争,但是无法避免synchronized/compareAndSet
带来的开销。
public class Test {
//指定随机数范围
public static void getRandom1() {
Random random = new Random();
System.out.println("生成随机数:" + random.nextInt(100));
}
//指定随机数范围
public static void getRandom2(int min, int max) {
Random random = new Random();
int randomInt = random.nextInt(max) % (max - min + 1) + min;
System.out.println(randomInt);
}
}
为什么不安全?
其中的报漏洞的解释是这样说的,在对安全性要求较高的环境中,使用能够生成可预测值的函数作为伪随机数据源,会产生Insecure Randomness(不安全随机性)
错误。
作用:性能快。追求性能使用ThreadLocalRandom
。
考虑到性能还是建议替换使用ThreadLocalRandom
(有3倍以上提升),这不是ThreadLocal
包装后的Random
,而是真正的使用ThreadLocal
机制重新实现的Random。
public class Test {
public static void getSecureRandom() {
// 生成 [0,10)的伪随机数, 左开右闭
int random = ThreadLocalRandom.current().nextInt(10);
}
}
作用:生成安全的随机数。
就是字面是的意思,安全的随机。
作用很明确,生成安全的、不可预测的随机数。
httpclient
中就有使用。
先看看怎么用:
public class Test {
public static void getSecureRandom() {
SecureRandom random1 = SecureRandom.getInstance("SHA1PRNG");
SecureRandom random2 = SecureRandom.getInstance("SHA1PRNG");
for (int i = 0; i < 5; i++) {
System.out.println(random1.nextInt() + " != " + random2.nextInt());
}
}
}
当不可预测性至关重要时, 如大多数对安全性要求较高的环境都采用随机性, 这时可以使用密码学的 PRNG。