Java.util 包的 Random 类用于生成伪随机数流。它使用 48 位种子,通过实施线性同余公式对其进行修改。线性同余公式的一般形式是 a n+1 = k * a n + c (mod m) 其中 a 0是种子,a 1 , a 2 , … a n , a n+1是随机数和k、c、m 是常数。
如果我们创建Random类的两个实例使用相同的种子值和调用的方法每一个相同的序列,它们都将返回数字相同的序列s。此属性由为此类定义的特定算法强制执行。该算法使用受保护的实用方法,该方法在调用时最多可以给出 32 个伪随机生成的位。随机的实例是线程–安全的。但是,如果跨线程使用相同的实例,它们可能会发生争用并导致性能不佳。 Random 实例在密码学上不是安全的,因此不应用于对安全敏感的应用程序。
句法:
public class Random extends Object implements Serializable
让我们举个例子,在下面给出的程序中,我们有 Random 类的三个实例。前两个具有传递给其构造函数的相同种子值。当我们使用 Random 类的 nextInt() 方法时,这会导致生成相同的数字。但是当我们更改种子的值并使用它来创建第三个实例时,生成的数字是不同的。这个例子清楚地证明了上述事实,即如果使用相同的种子值并且对两者使用相同的方法,则实例会生成相同的数字序列。
Java
// Java Program to illustrate Random class
// Importing Random class from java.util utility package
import java.util.Random;
// Class
// Main clas extending to parent Random class
public class RandomNumbers extends Random {
// Main driver method
public static void main(String[] args)
{
// Initialise a seed value
long seed = 18;
// Create an instance of Random using the seed value
Random r1 = new Random(seed);
// Prinitng the primitive datatype-integer
// by parsing using nextInt() method
System.out.println(r1.nextInt());
// Create a different instance of Random using the
// same seed value
Random r2 = new Random(seed);
// Again, prinitng the primitive datatype-integer
// by parsing using nextInt() method
System.out.println(r2.nextInt());
// Change the seed value to
// some other random value
seed = 34;
// Create a new instance using the updated seed
// value
Random r3 = new Random(seed);
// Lastly prinitng the primitive datatype-integer
// by parsing using nextInt() method
System.out.println(r3.nextInt());
}
}
Java
// Java Program to Illustrate ThreadLocalRandom class
// Importing ThreadLocalRandom class from utility package
// named java.util.concurrent package
import java.util.concurrent.ThreadLocalRandom;
// Class 1
// Main class extending parent class- Thread
class ThreadLocalRandomNumbers extends Thread {
// Method 1
// The run() method of the Thread class
// Must be defined by every class that extends it
public void run()
{
// Try block to check for exceptions
try {
// Initializaing a seed value to
// some random integer value
int seed = 10;
// Getting the current seed by
// calling over ThreadLocalRandom class and
// storing it in a integer variable
int r
= ThreadLocalRandom.current().nextInt(seed);
// Printing the generated number r
// The thread id is obtained using getId()
System.out.println(
"Thread " + Thread.currentThread().getId()
+ " generated " + r);
}
// Catch block to catch the exceptions
catch (Exception e) {
// Dipslay message on the console if
// the exception/s occur
System.out.println("Exception");
}
}
// Method 2
// Main driver method
public static void main(String[] args)
{
// Create two threads
ThreadLocalRandomNumbers t1
= new ThreadLocalRandomNumbers();
ThreadLocalRandomNumbers t2
= new ThreadLocalRandomNumbers();
// Starting th above created threads
// using the start() method
t1.start();
t2.start();
}
}
-1148559096
-1148559096
-1167027043
现在讨论下一个类,即我们的 ThreadLocalRandom 类
Java.util 包中的ThreadLocalRandom 类也用于生成伪随机数流。它是上面讨论的 Random 类的子类。顾名思义,此类生成与当前线程隔离的随机数。 ThreadLocalRandom 使用内部生成的种子值初始化,该值不可修改。使用 ThreadLocalRandom 而不是 Random 的共享实例将导致低争用和开销。 ThreadLocalRandom 就像它的父类一样,在密码学上并不安全。
句法:
public class ThreadLocalRandom extends Random
实现:让我们假设我们在主线程中创建两个简单的线程。在 run() 方法中,我们调用ThreadLocalRandom.current.nextInt() 。两个线程使用相同的种子值,即 10,但给出不同的结果,因为对nextInt()的调用被线程执行隔离。
例子
Java
// Java Program to Illustrate ThreadLocalRandom class
// Importing ThreadLocalRandom class from utility package
// named java.util.concurrent package
import java.util.concurrent.ThreadLocalRandom;
// Class 1
// Main class extending parent class- Thread
class ThreadLocalRandomNumbers extends Thread {
// Method 1
// The run() method of the Thread class
// Must be defined by every class that extends it
public void run()
{
// Try block to check for exceptions
try {
// Initializaing a seed value to
// some random integer value
int seed = 10;
// Getting the current seed by
// calling over ThreadLocalRandom class and
// storing it in a integer variable
int r
= ThreadLocalRandom.current().nextInt(seed);
// Printing the generated number r
// The thread id is obtained using getId()
System.out.println(
"Thread " + Thread.currentThread().getId()
+ " generated " + r);
}
// Catch block to catch the exceptions
catch (Exception e) {
// Dipslay message on the console if
// the exception/s occur
System.out.println("Exception");
}
}
// Method 2
// Main driver method
public static void main(String[] args)
{
// Create two threads
ThreadLocalRandomNumbers t1
= new ThreadLocalRandomNumbers();
ThreadLocalRandomNumbers t2
= new ThreadLocalRandomNumbers();
// Starting th above created threads
// using the start() method
t1.start();
t2.start();
}
}
Thread 12 generated 7
Thread 11 generated 0
现在我们已经完成了对这两个类的讨论,并对它们有了充分的了解。现在通过总结它们之间的差异来结束这篇文章。
Random | ThreadLocalRandom |
---|---|
If different threads use the same instance of Random it results in contention and consequent performance degradation. | There is no contention because the random numbers generated are local to the current thread. |
Uses Linear Congruential Formula to modify its seed value. | The Random generator is initialized using an internally generated seed. |
Useful in applications where each thread has its own set of Random instances to use. | Useful in applications where multiple threads use random numbers in parallel in thread pools. |
This is the Parent class. | This is the Child class. |