闲谈Random类与ThreadLocalRandom类

前言:这里将介绍两个能生成随机数的类 ThreadLocalRandom 类和 Random 类,与 Math 类所提供的随机方法 random( ) 相比,ThreadLocalRandom 类与 Random 类所提供的方法,都比 Math 类的 random( ) 方法提供了更多的方式,来生成各种伪随机数。它们可以生成浮点类型的伪随机数,也可以生成整数类型的伪随机数,还可以指定生成随机数的范围


1、Random 类

1.1、Random 类的介绍

​ Rndom 类专门用于生成一个伪随机数,它有两个构造器:

  • 一个构造器:使用默认的种子(以当前时间作为种子);

  • 另一个构造器:需要程序员显式传入一个 long 型整数的种子;

    1.2、Random 类的使用

    (1)代码表示
import java.util.Arrays;
import java.util.Random;

public class RandomTest {
    
    
    public static void main(String[] args) {
    
    
        Random rand = new Random();
        // 1、生成true或false
        System.out.println("rand.nextBoolean():\t" + rand.nextBoolean());

        // 2、生成随机字节并将它们放入用户提供的字节数组中。 bytes[i++] = (byte)nextInt();
        byte[] buffer = new byte[16];
        rand.nextBytes(buffer);
        System.out.println(Arrays.toString(buffer));

        // 3、生成 0.0~1.0 之间的伪随机 double 数
        System.out.println("rand.nextDouble():\t" + rand.nextDouble());

        // 4、生成 0.0~1.0 之间的伪随机 float 数
        System.out.println("rand.nextFloat():\t" + rand.nextFloat());

        // 5、生成平均值是 0.0,标准差是 1.0 的伪高斯数
        System.out.println("rand.nextGaussian():\t" + rand.nextGaussian());

        // 6、生成一个处于 int 整数取值范围的伪随机整数
        System.out.println("rand.nextInt():\t" + rand.nextInt());
        /* 生成 min-max:[min,max] 之间的伪随机整数,则为 rand.nextInt(max-min+1)+min,推导:
         [0, max]       ->  next.nextInt(max + 1);
         [min, max+min] ->  next.nextInt(max + 1) + min;
         [min, max]     ->  next.nextInt(max + 1 - min) + min;*/
        System.out.println("next.nextInt(max + 1 - min) + min:\t" + rand.nextInt(20 + 1 - 15) + 15);
    }
}
(2)运行结果
rand.nextBoolean()true
[-26, -98, -90, 107, 24, -61, 125, -84, -41, 94, -56, -17, 26, -125, -94, -109]
rand.nextDouble()0.8362498709465734
rand.nextFloat()0.70504546
rand.nextGaussian()-1.108647283595758
rand.nextInt()-1780316130
next.nextInt(max + 1 - min) + min:	415

1.3、Random 类的注意点

​ 从上面程序中可以看出,Random 可以提供很多方法来生成伪随机数。Random 使用一个 48位的种子,如果这个类的两个实例是用同一个种子创建,对它们以同样的顺序调用方法,则它们会产生相同的数字序列。测试如下所示:

(1)代码表示
import java.util.Random;

public class SeedTest {
    
    
    public static void main(String[] args) {
    
    
        //显示的设置种子数为50
        Random r1 = new Random(50);
        System.out.println("第一个种子为 50 的Random对象");
        System.out.println("r1.nextBoolean():\t" + r1.nextBoolean());
        System.out.println("r1.nextDouble():\t" + r1.nextDouble());
        System.out.println("r1.nextGaussian():\t" + r1.nextGaussian());
        System.out.println("----------------------------");

        //显示的设置种子数为50
        Random r2 = new Random(50);
        System.out.println("第二个种子为 50 的Random对象");
        System.out.println("r2.nextBoolean():\t" + r2.nextBoolean());
        System.out.println("r2.nextDouble():\t" + r2.nextDouble());
        System.out.println("r2.nextGaussian():\t" + r2.nextGaussian());
        System.out.println("----------------------------");

        //显示的设置中字数为100
        Random r3 = new Random(100);
        System.out.println("种子为 100 的Random对象");
        System.out.println("r3.nextBoolean():\t" + r3.nextBoolean());
        System.out.println("r3.nextDouble():\t" + r3.nextDouble());
        System.out.println("r3.nextGaussian():\t" + r3.nextGaussian());
    }
}
(2)运行结果
第一个种子为 50 的Random对象
r1.nextBoolean()true
r1.nextDouble()0.5978920402252371
r1.nextGaussian()1.3268136608950492
----------------------------
第二个种子为 50 的Random对象
r2.nextBoolean()true
r2.nextDouble()0.5978920402252371
r2.nextGaussian()1.3268136608950492
----------------------------
种子为 100 的Random对象
r3.nextBoolean()true
r3.nextDouble()0.7346627443280227
r3.nextGaussian()-1.0560180403978943

​ 从上面运行结果来看,只要两个 Random 对象的种子相同,并且方法的调用顺序也相同(没看错哦 _,如果顺序不一致产生的数也会不同),他们就会产生相同的数字序列。也就是说,Random 产生的数字并不是真正随机的,而是一种伪随机

​ 为了避免两个 Random 对象产生相同的数字序列,通常推荐使用当前时间作为 Random 对象的种子(也就是 Random 的默认种子 ( ̄┰ ̄*))。代码如下所示:

Random rand = new Random(System.currentTimeMillis());

2、ThreadLocalRandom 类

2.1、ThreadLocalRandom 类的介绍

​ ThreadLocalRandom 类是 Java7 新增的一个类,它是 Random 的增强版。在并发访问的环境下,使用 ThreadLocalRandom 來代替 Random 可以减少多线程资源竞争,最终保证系统具有更好的线程安全性。ThreadLocalRandom 类的用法与 Random 类的用法基本相似,它提供个静态的 current( ) 方法来获取 ThreadLocalRandom 对象,获取该对象之后即可调用各种 nextXxx( ) 方法来获取伪随机数。

2.2、ThreadLocalRandom 类的使用

(1)代码表示
import java.util.concurrent.ThreadLocalRandom;

public class ThreadLocalRandomTest {
    
    
    public static void main(String[] args) {
    
    
        // 通过静态方法 current() 来获取本地现场的随机对象
        ThreadLocalRandom rand = ThreadLocalRandom.current();
        // 生成 [4, 20) 之间的随机整数
        System.out.println("rand.nextInt(4, 20):\t" + rand.nextInt(4, 20));
        // 生成 [2.0, 10.0) 之间的伪随机浮点数
        System.out.println("rand.nextDouble(2.0, 10.0):\t" + rand.nextDouble(2.0, 10.0));
    }
}
(2)运行结果
rand.nextInt(4, 20)13
rand.nextDouble(2.0, 10.0)7.176239930654342

猜你喜欢

转载自blog.csdn.net/qq_33931634/article/details/106974203