简述

java中常用的三个随机数类:

  1. Random
  2. ThreadLocalRandom
  3. SecureRandom

Random 是最常用的类,ThreadLocalRandom 性能快,SecureRandom 注重安全。
下面简单分析3个类的使用。

Random

伪随机数生成器,可以传一个种子来生成随机数。
种子就是一个指定的变量,用来参与生成随机数,如果什么都不传,默认使用System.nanoTime() 来参与生成。
特点:Random 是线程安全的、不是加密安全的,因为是伪随机数。
Random用到了compareAndSet + synchronized来解决线程安全问题,虽然可以使用ThreadLocal<Random>来避免竞争,但是无法避免synchronized/compareAndSet带来的开销。

生成指定范围随机数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
考虑到性能还是建议替换使用ThreadLocalRandom(有3倍以上提升),这不是ThreadLocal包装后的Random,而是真正的使用ThreadLocal机制重新实现的Random。

1
2
3
4
5
6
7
public class Test {

public static void getSecureRandom() {
// 生成 [0,10)的伪随机数, 左开右闭
int random = ThreadLocalRandom.current().nextInt(10);
}
}

SecureRandom

作用:生成安全的随机数。
就是字面是的意思,安全的随机。
作用很明确,生成安全的、不可预测的随机数。
httpclient中就有使用。
先看看怎么用:

1
2
3
4
5
6
7
8
9
10
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。