Creación de múltiples grupos de objetos de tamaño variable en Java

El patrón de grupo de objetos es un patrón de diseño de creación de software que se usa en situaciones en las que el costo de inicializar una instancia de clase es muy alto. Básicamente, un grupo de objetos es un contenedor que contiene cierta cantidad de objetos. Entonces, cuando se toma un objeto del grupo, no está disponible en el grupo hasta que se devuelve. 
Los objetos en el grupo tienen un ciclo de vida: 

  • Creación
  • Validación
  • Destruir.

La agrupación de objetos puede proporcionar una gran mejora de la velocidad; funciona mejor cuando el costo de inicializar una instancia de clase es alto, el ritmo de creación de instancias es alto y la cantidad de instancias en uso en un momento dado es baja.
El diseño de Object Pool es útil cuando los objetos son costosos de construir y solo necesitan usarse por un corto período de tiempo. En este patrón de diseño, hacemos un seguimiento de qué objetos instanciados están en uso y cuáles son accesibles.

¿Cómo crear múltiples grupos de objetos?

Todos sabemos cómo crear un solo grupo de objetos. Pero puede haber un requisito para crear múltiples grupos de objetos de tamaño variable. Esto significa que en lugar de crear un solo grupo de objetos de tamaño fijo, podemos tener varios grupos y cada grupo tiene una cantidad diferente de objetos totales.

¿Cuál es el requisito en tiempo real para ello?

La asignación de memoria según sea necesario para el manejo de errores o en escenarios emergentes en la programación se puede lograr generando múltiples grupos de memoria de tamaño variable.

Hay algunos objetos para los que la producción de un nuevo objeto parece ser un poco más costosa, ya que no se consideran livianos. Los objetos de conexión de base de datos, los objetos de analizador, la generación de subprocesos, etc., son ejemplos. Es posible que tengamos que construir numerosos grupos de objetos de este tipo en cualquier aplicación. Debido a que la generación de dichos objetos es costosa, tendrá un impacto negativo en el rendimiento de cualquier programa. Podemos usar el mismo objeto una y otra vez.

Implementación:
aquí estamos creando una clase «Subproceso» cuyos Objetos están allí en grupos y otra clase «Subproceso» que se utiliza para crear múltiples grupos de Objetos «Subproceso».

En nuestra clase Clase de subprocesos (clase 1)

Tenemos miembros de datos:

  • «uniqueId» Almacena una identificación única generada para cada objeto de subproceso.
  • “nombre” Mantiene el nombre del objeto hilo.

En nuestra clase clase ThreadPool (clase 2)

Tenemos miembros de datos:

  • isFirst = verdadero para mantener el valor verdadero inicialmente y cada vez que se crea el primer objeto Subproceso en el grupo, después de la creación del primer objeto, se establece en falso.
  • myThreads[] de tipo Thread, que es una referencia de array que se referirá al objeto Thread Class (Thread Pool Array)
  • isUsed[] de tipo booleano, que es una array para realizar un seguimiento de los objetos de Thread que están en uso actualmente
  • noOfThreadPools para llevar la cuenta del número de grupos de subprocesos y es una propiedad de nivel de clase
  • ThreadreferenceCount para llevar la cuenta del número de referencias de subprocesos en un grupo en particular
  • poolNum para almacenar un número único dado a cada grupo creado

Ejemplo

Java

// Java Program to Creating Multiple Pools Of Objects of
// Variable Size
 
// Importing required classes
import java.io.*;
import java.util.*;
 
// Class 1
// Helper class
class Thread {
 
    // Members of this class
    private int uniqueId;
    private static int uniqueIDGen = 0;
    private String thread_name;
 
    // Constructor that initializes the objects of Thread
    // class
    Thread() { uniqueId = generateUniqueId(); }
 
    // Method 1
    // To set the value of the data member,
    // name of the Thread's Object
    public void setNameOfThread(String name)
    {
        thread_name = name;
    }
 
    // Method 2
    public String getNameOfThread() { return thread_name; }
 
    // Method 3
    // To generate a unique id for each Thread's Object
    private int generateUniqueId() { return uniqueIDGen++; }
 
    // Method 4
    // To Compare that the "this" reference and
    // "t1" reference refer to same object
    public boolean compare(Thread t1)
    {
 
        if (t1.uniqueId == this.uniqueId) {
            return true;
        }
 
        else {
            return false;
        }
    }
}
 
// Class 2
// Helper class
class ThreadPool {
 
    // member variables of this class
 
    // To keep true whenever 1st object of a pool is
    // created,
    // after 1st object creation, it is set to false
    private boolean isFirst = true;
 
    // Array reference of myThread (Thread Pool Array)
    private Thread myThreads[] = null;
 
    // Array to Keep track that which Thread's objects
    // are in use currently
    private boolean isUsed[] = null;
 
    private int n;
 
    // To keep count of no of Thread Pools and
    // is a class level Property
    private static int noOfThreadPools = 0;
 
    // Keeping count of no of thread references
    // in a particular pool
    private int ThreadreferenceCount = 0;
 
    // To Give a unique number to every Pool Created
    private int poolNum = 0;
 
    // Constructor of class 2
    public ThreadPool()
    {
 
        noOfThreadPools++;
        poolNum = noOfThreadPools;
    }
 
    // Method 1
    // To give "size" of each Thread pool and
    // creating size no of objects of Thread Type,
    // returning true if successful, else false
    public boolean initialize(int size)
    {
 
        boolean status = false;
 
        if (true == isFirst) {
 
            isFirst = false;
            n = size;
 
            // Assign memory of reference of array
            // using new keyword
            myThreads = new Thread[n];
 
            for (int i = 0; i < n; i++) {
 
                // Creating new object in heap of Thread
                // Class & myThread[i] reference refer it
                myThreads[i] = new Thread();
 
                // we are assigning thread name to each
                // thread
                String name = Integer.toString(i + 1);
 
                name = name.concat(
                    " is the thread number of the pool ");
                name = name.concat(
                    Integer.toString(poolNum));
 
                // Name assigning finishes
                myThreads[i].setNameOfThread(name);
            }
 
            // Creating new array of boolean type which is
            // referred by isUsed reference
            isUsed = new boolean[n];
 
            for (int i = 0; i < n; i++) {
 
                // Now making isUsed false for all the
                // references false,
                // false because when initializing, no
                // reference from outside is referring to
                // any of the objects created (from o to
                // size-1)
                isUsed[i] = false;
            }
 
            status = true;
        }
 
        return status;
    }
 
    // Method 2
    // To get reference of the Thread Objects Present in the
    // Pool If no object is free, it returns null
    public Thread getReference()
    {
 
        Thread threadToReturn = null;
 
        if (ThreadreferenceCount < n) {
 
            for (int i = 0; i < n; i++) {
 
                // When no reference from outside the class
                // is referring to object myThread[i],
                // isUsed[i] is false
                if (false == isUsed[i]) {
 
                    threadToReturn = myThreads[i];
 
                    // Make isUsed[i] as true because we are
                    // returning a reference to the object
                    // referred by myThread[i]
                    isUsed[i] = true;
 
                    // Incrementing the count because we are
                    // returning a reference to the object
                    // referred by myThread[i] to outside
                    // world now this object cant be referred
                    // by another reference from outside
                    ThreadreferenceCount++;
 
                    // Break keyword
                    break;
                }
            }
        }
 
        return threadToReturn;
    }
 
    // Method 3
    // To release the outside world reference;
    // Here : "thread" - passed as parameter
    public void releaseReference(Thread thread)
    {
 
        if (ThreadreferenceCount > 0) {
 
            for (int i = 0; i < n; i++) {
 
                // Compare the "thread" parameter with every
                // reference and release the matched one by
                // making isUsed[i] = false;
                if (true == thread.compare(myThreads[i])) {
 
                    // Make isUsed[i] is false to show no
                    // reference from
                    // outside the class is referring to
                    // object myThread[i]
                    isUsed[i] = false;
 
                    // Decrementing the count because we are
                    // releasing a reference to the object
                    // in outside world
 
                    ThreadreferenceCount--;
 
                    break;
                }
            }
        }
    }
 
    // Method 4
    // To make all the objects free for garbage collection
    // To restore to initial situation
    public boolean deInitialize()
    {
 
        boolean status = false;
 
        if (isFirst = false) {
            status = true;
        }
 
        // This condition is not required if one wants to
        // deinitialize() even if the references are present
        // outside
        else if (ThreadreferenceCount == 0) {
 
            for (int i = 0; i < n; i++) {
                myThreads[i] = null;
            }
 
            myThreads = null;
            isUsed = null;
 
            n = 0;
            isFirst = true;
            status = true;
        }
 
        return status;
    }
}
 
// Class 3
// Min class
public class Main {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Display message on console for better readability
        System.out.println(
            "*****************POOL1 Of Threads Created*****************");
 
        // Creating object of class 2 in class 3 main()
        // method
        ThreadPool p1 = new ThreadPool();
 
        // Creating pool of 2 objects
        if (p1.initialize(2)) {
 
            System.out.println("Pool 1 initialized");
        }
        else {
 
            System.out.println("Pool 1 not initialized");
        }
 
        // Now getting 2 references to the 2 Objects from
        // this pool
 
        // Thread 1
        Thread t1 = p1.getReference();
        if (t1 != null) {
 
            System.out.println(t1.getNameOfThread());
        }
        else {
 
            System.out.println(
                " t1 do not refer any object");
        }
 
        // Thread 2
        Thread t2 = p1.getReference();
        if (t2 != null) {
 
            System.out.println(t2.getNameOfThread());
        }
        else {
 
            System.out.println(
                " t2 do not refer any object");
        }
 
        // Thread 3
        Thread t3 = p1.getReference();
        if (t3 != null) {
 
            System.out.println(t3.getNameOfThread());
        }
        else {
 
            System.out.println(
                " t3 do not refer any object");
        }
 
        // Releasing all the references of pool 1
        p1.releaseReference(t1);
        t1 = null;
        p1.releaseReference(t2);
        t2 = null;
 
        // As we have not used deInitialize() method, we
        // cannot initialize the pool p1 again
        if (p1.initialize(2)) {
 
            // Print statement
            System.out.println("Pool 1 initialized");
        }
        else {
 
            // Print statement
            System.out.println(
                "Pool 1 not initialized as it was already initialized\n");
        }
 
        // Creating pool 2
 
        // Display message on console for better readability
        System.out.println(
            "*****************POOL2  Of Threads Created*****************");
 
        ThreadPool p2 = new ThreadPool();
 
        // Creating pool of 3 objects
        p2.initialize(3);
 
        Thread tp1 = p2.getReference();
 
        if (tp1 != null) {
 
            System.out.println(tp1.getNameOfThread());
        }
        else {
 
            System.out.println(
                "tp1 dont refer to any object");
        }
 
        // Releasing references of pool 2
        p2.releaseReference(tp1);
        tp1 = null;
 
        // Deinitializing both the pools
        // using deInitialize() method
        p1.deInitialize();
        p2.deInitialize();
    }
}
Producción

*****************POOL1 Of Threads Created*****************
Pool 1 initialized
1 is the thread number of the pool 1
2 is the thread number of the pool 1
 t3 do not refer any object
Pool 1 not initialized as it was already initialized

*****************POOL2  Of Threads Created*****************
1 is the thread number of the pool 2

Explicación de salida: 

  • Aquí, creamos dos grupos de objetos de subprocesos mediante:
ThreadPool p1 = new ThreadPool() & ThreadPool p2 = new ThreadPool() 
  • Luego llamamos al método initialize() en p1 y p2 dando tamaño (objetos «Subproceso» totales en el grupo) – 2 y 3 respectivamente.
  • Luego, se crean 2 referencias de la clase Thread (t1 y t2) que hacen referencia a objetos (de tipo Thread) en Pool p1.
  • Se crea una tercera referencia (t3) de la clase Thread, y estamos tratando de obtener Object (llamando a getReference() en p1) del grupo p1 para que t3 pueda referirlo. Pero t3 no se refiere a ningún objeto ya que el tamaño de Pool p1 es 2, solo 2 referencias del mundo exterior pueden referirse a los 2 objetos en el pool.
  • Luego liberamos ambas referencias (t1 y t2) llamando al método releaseReference(). Ahora los objetos en el grupo están disponibles y las referencias del mundo exterior pueden referirse a ellos llamando al método getReference() en p1.
  • De manera similar, creamos otra referencia (tp1) pero se refiere al objeto Thread contenido en el grupo p2 como llamamos al método getReference() en p2.
  • Luego liberamos las referencias (tp1) llamando al método releaseReference().
  • Al final, llamamos al método deInitialize() en p1 y p2 para devolver el grupo de p1 y p2 a la condición inicial que tenía antes de llamar a initialize().
     

Publicación traducida automáticamente

Artículo escrito por sameekshakhandelwal1712 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 *