这是我参与更文挑战的第14天,活动详情查看: 更文挑战
Random
其实Math类的方法中也有生成伪随机数的方法,我们来看一下例子:
public class Test {
public static void main(String[] args) {
//Math.random()生成的伪随机数范围是[0.0,1.0)
System.out.println("Math.random()生成的伪随机数是:"+Math.random());
}
}
今天我们要讲的随机数要比这个功能强大很多。
Random类可以生成浮点数类型的伪随机数,也可以生成整数类型的伪随机数,还可以指定生成随机数的范围。
Random类专门用于生成一个伪随机数。它有两个构造器。一个构造器使用默认的种子(以当前的时间为 种子),另一个构造器需要传入一个long型整数的种子。 我们来看一个例子:
public class Test {
public static void main(String[] args) {
Random random = new Random();
//生成int范围内的伪随机数
System.out.println(random.nextInt());
//生成long范围内的伪随机数
System.out.println(random.nextLong());
//随机生成true和false
System.out.println(random.nextBoolean());
byte[] b = new byte[10];
random.nextBytes(b);
System.out.println(Arrays.toString(b));
//生成0.0~1.0之间的double数
System.out.println(random.nextDouble());
//生成0.0~1.0之间的float数
System.out.println(random.nextFloat());
}
}
对于Random类来说如果这个类的实例使用的是相同的种子,那么如果以相同的顺序调用,将会产生相同的顺序。如下例:
public class Test {
public static void main(String[] args) {
Random random1 = new Random(10);
System.out.println("这是第一个种子为10的random产生的伪随机数");
System.out.println(random1.nextInt());
System.out.println(random1.nextDouble());
System.out.println(random1.nextBoolean());
Random random2 = new Random(10);
System.out.println("这是第二个种子为10的random产生的伪随机数");
System.out.println(random2.nextInt());
System.out.println(random2.nextDouble());
System.out.println(random2.nextBoolean());
Random random3 = new Random(100);
System.out.println("这是第一个种子为100的random产生的伪随机数");
System.out.println(random3.nextInt());
System.out.println(random3.nextDouble());
System.out.println(random3.nextBoolean());
}
}
看到上面结果,我们就知道了为什么说是伪随机数,这些随机数都是根据种子,然后使用算法实现的。并不具备真正的随机。
为了避免上面这种情况,我们通常使用当前的时间来作为种子,如下代码:
Random rand = new Random(System.currentTimeMillis());
ThreadLocalRandom
ThreadLocalRandom的使用方式与Random基本类似。但它提供了一个静态的current()方法来获取ThreadLocalRandom对象,获取该对象后就可以像Random一样调用各种方法来获取伪随机数。
如下:
ThreadLocalRandom rand = ThreadLocalRandom.current();
//生成一个1~100范围内的随机数
int num = rand.nextInt(1,100);
在并发访问的环境下使用ThreadLocalRandom来代替Random可以减少多线程的资源竞争,使系统具有更好的线程安全性。