Clases aleatorias vs ThreadLocalRandom en Java

La clase aleatoria del paquete java.util se utiliza para generar un flujo de números pseudoaleatorios. Utiliza una semilla de 48 bits, que se modifica implementando una fórmula lineal congruente. La forma general de una Fórmula Lineal Congruencial es a n+1 = k * a n + c (mod m) donde a 0 es la semilla, a 1 , a 2 , … a n , a n+1 son los números aleatorios y k, c, m son constantes.

Si creamos dos instancias de la clase Random con el mismo valor inicial y llamamos a la misma secuencia de métodos para cada una, ambas devolverán secuencias idénticas de números. Esta propiedad se aplica mediante algoritmos específicos definidos para esta clase. Los algoritmos utilizan un método de utilidad protegido que, al ser invocado, puede proporcionar hasta 32 bits generados pseudoaleatoriamente. Las instancias de Random son seguras para subprocesos. Sin embargo, si se utilizan las mismas instancias en todos los subprocesos, pueden sufrir contención y dar como resultado un rendimiento deficiente. Las instancias de Random no son criptográficamente seguras y, por lo tanto, no deben usarse para aplicaciones sensibles a la seguridad.

Sintaxis:

public class Random extends Object implements Serializable

Tomemos un ejemplo, en el programa que se muestra a continuación tenemos tres instancias de la clase Random. Los dos primeros tienen el mismo valor semilla pasado a su constructor. Esto da como resultado que se genere el mismo número cuando usamos el método nextInt() de la clase Random. Pero cuando cambiamos el valor de la semilla y la usamos para crear la tercera instancia, el número que se genera es diferente. Este ejemplo demuestra claramente el hecho mencionado anteriormente sobre las instancias que generan la misma secuencia de números si se usa el mismo valor inicial y los mismos métodos para ambos. 

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);
 
        // Printing 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, printing 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 printing the primitive datatype-integer
        // by parsing using nextInt() method
        System.out.println(r3.nextInt());
    }
}
Producción

-1148559096
-1148559096
-1167027043

Ahora pensando en la siguiente clase que es nuestra clase ThreadLocalRandom 

La clase ThreadLocalRandom presente dentro del paquete java.util también se usa para generar un flujo de números pseudoaleatorios. Es una subclase de la clase Random discutida anteriormente. Como sugiere el nombre, esta clase genera números aleatorios aislados del hilo actual. Un ThreadLocalRandom se inicializa utilizando un valor inicial generado internamente que no se puede modificar de otra manera. El uso de ThreadLocalRandom en lugar de instancias compartidas de Random dará como resultado una contención y una sobrecarga bajas. ThreadLocalRandom, al igual que su clase principal, no es criptográficamente seguro.

Sintaxis: 

public class ThreadLocalRandom extends Random 

Implementación: tomemos un escenario en el que estamos creando dos hilos simples en el principal. Dentro del método run() llamamos a ThreadLocalRandom.current.nextInt() . Ambos subprocesos usan el mismo valor de semilla, es decir, 10, pero dan resultados diferentes porque la ejecución del subproceso aísla la llamada a nextInt()

Ejemplo 

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 {
 
            // Initializing 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) {
 
            // Display 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();
    }
}
Producción

Thread 12 generated 7
Thread 11 generated 0

Ahora hemos terminado de discutir ambas clases y tenemos una comprensión adecuada de ambas. Ahora terminando el artículo concluyendo las diferencias entre ellos.

Aleatorio SubprocesoLocalAleatorio
Si diferentes subprocesos utilizan la misma instancia de Random, se produce una contención y la consiguiente degradación del rendimiento. No hay conflicto porque los números aleatorios generados son locales para el subproceso actual.
Utiliza la fórmula lineal congruente para modificar su valor inicial. El generador aleatorio se inicializa utilizando una semilla generada internamente.
Útil en aplicaciones donde cada subproceso tiene su propio conjunto de instancias aleatorias para usar. Útil en aplicaciones donde varios subprocesos usan números aleatorios en paralelo en grupos de subprocesos.
Esta es la clase de Padres. Esta es la clase Niño.

Publicación traducida automáticamente

Artículo escrito por ManasiKirloskar y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *