1、Random
常用随机数生成类,使用当前系统时间作为种子生成随机数。
伪随机性
- 线程安全
- 可以设置seed,生成同一随机数
- 默认使用当前系统时间,有迹可循
Random r1 = new Random();
Random r2 = new Random(2);
System.out.println(r1.nextInt(10)); //每次运行结果不同
System.out.println(r2.nextInt(10)); //每次运行结果相同
2、SecureRandom
2.1 默认的种子生成策略
满足加密要求的强随机数生成器,收集随机事件(鼠标点击等)生成随机数
- 可以设置seed,生成同一随机数
- 默认使用随机事件,无迹可寻
SecureRandom s1 = new SecureRandom();
System.out.print(s1.nextInt());
byte[] seed = "seed".getBytes();
SecureRandom s2 = new SecureRandom(seed);
System.out.print(s2.nextInt());
2.2 /dev/random
Linux操作系统中,有一个特殊的设备文件 /dev/random,可以用作随机数发生器或伪随机数发生器。
-
/dev/random:收集系统环境中的噪声数据生成熵池;
适用于对随机数质量要求比较高的请求,可生成高随机性的公钥或一次性密码本;
若熵池空了,对/dev/random 的读操作将会被阻塞,直到收集到了足够的环境噪声为止。
-
/dev/urandom:非阻塞的随机数发生器,它会重复使用熵池中的数据以产生伪随机数据;
可以作为生成较低强度密码的伪随机数生成器。
启动应用程序时可以通过参数 -Djava.security.egd=file:/dev/urandom 来指定 seed 源。
*错误
private Random rand = SecureRandom.getInstanceStrong();
//此种方式采用/dev/random作为种子,可能会造成阻塞
SecureRandom s1 = new SecureRandom();
//使用 /dev/urandom 生成种子,不会产生阻塞。
3、ThreadLocalRandom
1.7版本增加,继承自Random类
多线程时使用
构造方法私有化,采用静态工厂模式创建
ThreadLocalRandom t = ThreadLocalRandom.current();
System.out.println(t.nextInt());
优点:
- 在多线程并发情况下,减少多线程资源竞争,保证线程安全。
ThreadLocalRandom使用ThreadLocal的原理,让每个线程内持有一个本地的种子变量,该种子变量只有在使用随机数时候才会被初始化,多线程下计算新种子时候是根据自己线程内维护的种子变量进行更新,从而避免了竞争。
4、UUID
通用唯一识别码
数据库唯一ID时使用
String u=UUID.randomUUID().toString();
System.out.println(u);