Random和Java7的“增强版的Random”

388 阅读2分钟

这是我参与更文挑战的第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());
	}
}

image.png 今天我们要讲的随机数要比这个功能强大很多。 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());
	}
}

image.png 看到上面结果,我们就知道了为什么说是伪随机数,这些随机数都是根据种子,然后使用算法实现的。并不具备真正的随机。

为了避免上面这种情况,我们通常使用当前的时间来作为种子,如下代码:

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可以减少多线程的资源竞争,使系统具有更好的线程安全性。