Skip to content
Related Articles

Related Articles

Improve Article

Creating Multiple Pools of Objects of Variable Size in Java

  • Last Updated : 15 Sep, 2021

Object pool pattern is a software creational design pattern that is used in situations where the cost of initializing a class instance is very high. Basically, an Object pool is a container that contains some amount of objects. So, when an object is taken from the pool, it is not available in the pool until it is put back. 
Objects in the pool have a lifecycle: 

  • Creation
  • Validation
  • Destroy.

Object pooling can provide a large speed improvement; it works best when the cost of initializing a class instance is high, the pace of instantiation is high, and the number of instantiations in use at any given moment is low.
The Object Pool design is useful when objects are expensive to construct and only need to be used for a short period of time. In this design pattern, we keep track of which instantiated objects are in use and which are accessible.

How to create Multiple pools of Objects?

We all know how to create a single pool of objects. But there may be a requirement to create multiple pools of objects of variable size. This means instead of creating a single pool of objects o fixed size, we can have multiple pools & each pool has a different number of total objects.



What is the real-time requirement for it?

Memory allocation as needed for error handling or in emergent scenarios in programming can be accomplished by generating multiple variable-size memory pools.

There are a few objects for which the production of a new object appears to be slightly more expensive since they are not considered lightweight. Database connection objects, parser objects, thread generation, and so forth are examples. We may have to construct numerous such pools of objects in any application. Because the generation of such objects is expensive, it will have a negative impact on the performance of any program. We can use the same object again & again.

Implementation:
We are here creating a class “Thread” whose Objects are there in pools & another class “ThreadPool” that is used to create multiple pools of “Thread” Objects.

In our class Thread class(class 1)

We have data members:

  • “uniqueId” Stores unique id generated for each thread object.
  • “name” Keeps the name for the thread object.

In our class ThreadPool class(class 2)

We have data members:

  • isFirst = true to keep true initially & whenever 1st Thread object in pool is created, after 1st object creation, it is set to false.
  • myThreads[] of type Thread which is an array reference that will refer to the Thread Class object(Thread Pool Array)
  • isUsed[]  of type boolean which is an array to Keep track that which Thread’s objects are in use currently
  • noOfThreadPools  to keep count of no of Thread Pools & is a class level Property
  • ThreadreferenceCount  to keep count of no of thread references in a particular pool
  • poolNum to store unique number given to every Pool Created

Example

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();
    }
}
Output
*****************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

Output explanation: 

  • Here, we create two pools of Thread Objects by:
ThreadPool p1 = new ThreadPool() & ThreadPool p2 = new ThreadPool() 
  • Then we called initialize() method on p1 & p2 giving size (total “Thread” Objects in the pool ) – 2 & 3 respectively.
  • Then 2 references of Thread class ( t1 & t2) are created who are referencing Objects (of Thread type) in Pool p1.
  • A 3rd  reference(t3) of Thread class is created, and we are trying to get Object (by calling getReference() on p1)from pool p1 so that t3 can refer it. But t3 do not refer to any object as Pool p1 size is 2, only 2 references from the outside world can refer to the 2 objects in the pool.
  • Then we release both the references (t1 & t2) by calling the method releaseReference(). Now the objects in the pool are available & the outside world references can refer them by calling the method getReference() on p1.
  • Similarly, we created another reference (tp1) but it refers to the Thread object contained in the pool p2 as we called the method getReference() on p2.
  • Then we release the references (tp1) by calling the method releaseReference().
  • At the end we call method deInitialize() on p1 & p2 bring back p1 & p2 pool to the starting condition that was before calling initialize().
     

Attention reader! Don’t stop learning now. Get hold of all the important Java Foundation and Collections concepts with the Fundamentals of Java and Java Collections Course at a student-friendly price and become industry ready. To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.




My Personal Notes arrow_drop_up
Recommended Articles
Page :