Object pool design pattern in Java works on the reusability concept of the object creation. This pattern is most efficient when it is expensive to create objects and can cause memory issues if multiple objects are created. It helps to improve the performance of the application.

Object pool design pattern works on the concept of object pooling. In other words, whenever there are multiple clients trying to access the same objects which are stateless in nature and expensive to create, we can use the pool of reusable objects.

When to use the Object pool pattern?

  • Creating multiple expensive objects of the same type.
  • We know about the system that how many objects can be created in the pool. Along with the locking period of one reusable object inside the pool.
  • When running different parallel processes at the same time

Working principle of Object pool pattern.

Object pool pattern works on the principle of reusability of the objects by sharing the same reusable objects to different clients. This managing of the reusable object is taken care of by the reusable pool which is a singleton class.

Every reusable pool is having its size limit. The size limit states the total number of different objects that can be created inside the application. To explain this more clear, let’s take a simple example below.

Let’s say we have 4 clients named Client A, Client B, and Client C. One reusable object pool with size 2 which is having one object named obj1 inside it.

Now when the execution starts, let’s say Client A wants to get access to the reusable object and requests for that, then the pool checks that if it’s having the free object or not. In our case, we are having one free object obj1 which will now be accessed by the client A. During this time the obj1 will be in a locked state and no other client can request for that object.

Let’s say at the same time Client B comes in the picture and try to access the same object and request an object from the object pool. Now object pool will again check that if it is having the resource that can be given to client B and it finds that there is only one object obj1 which is already in use and client A has not released this object yet.

In this case when there are not enough resources to distribute inside the object pool. Pool checks the size and if there is an availability of size then it will create a new object and give it to the client.

In this case, the size of the pool is 2 and the available resource is only one. So the pool creates one new object named obj2 and will give it to Client B. Please note that now we are having two objects which are locked by two clients. They will be in a locked state until the time the client doesn’t release the object.

In the case where one more client Client C comes up and says I want to use the object and request it from the pool. All the objects are locked and no more new objects can be created because the size of the pool is already full. Then Client C will have to wait until the occupied reusable objects are not ready to use.

In the above example, it is important that the pool works perfectly and distributes the resources in an efficient way. And clients try to release the resources as soon as possible after the work is done.

Example and Use-case of Object pool pattern.

Let’s take the most common and real-world example of a problem which is faced by most of the application that interacts with the databases.

The problem to connect with the database which involves the creation of Database connection objects. The creation of the connection object is an expensive work to do as it involves loading drivers, validating the statements and several other things.

So, as a solution to the above problem, we will be creating a pool of connection objects. This pool will hold expensive objects which can be distributed to clients as per the requirement. For this, We will also be creating an interface to get the reusable objects from that pool.

Practical Implementation of the above problem.

The below class ReusablePool.java is an abstract class that will be acting as a base for the connection class. In the class, we are using `hashtable to check the state of the object whether it is in a locked or unlocked state.

The variable expirationtime is the object expires time which is 50seconds. After this certain time, the object will be auto expired from the system.

We have introduced three methods which will be overridden by the subclass which to work as below:
createObject() : Creating the Connection Object.
validateObject() : Validation of the already created object. If the connection object is not closed then only it will return true.
expiredObject(): This method will close the connection object.

package javadesignpatterns.creational.objectpoolpattern;

import java.util.Enumeration;
import java.util.Hashtable;

public abstract class ReusablePool<T> {
  private long expirationTime;

  private Hashtable<T, Long> lock, unlock;

  public ReusablePool() {
    expirationTime = 50000; // 50 seconds
    lock = new Hashtable<T, Long>();
    unlock = new Hashtable<T, Long>();
  }

  protected abstract T createObject();

  public abstract boolean validateObject(T o);

  public abstract void expiredObject(T o);

  public synchronized T getInstance() {
    long now = System.currentTimeMillis();
    T t;
    if (unlock.size() > 0) {
      Enumeration<T> e = unlock.keys();
      while (e.hasMoreElements()) {
        t = e.nextElement();
        if ((now - unlock.get(t)) > expirationTime) {
          // object has expired
          unlock.remove(t);
          expiredObject(t);
          t = null;
        } else {
          if (validateObject(t)) {
            unlock.remove(t);
            lock.put(t, now);
            return (t);
          } else {
            // object failed validation
            unlock.remove(t);
            expiredObject(t);
            t = null;
          }
        }
      }
    }
    // no objects available, create a new one
    t = createObject();
    lock.put(t, now);
    return (t);
  }
  public synchronized void releaseObject(T t) {
    lock.remove(t);
    unlock.put(t, System.currentTimeMillis());
  }
}

The below class ConnectionPool.java is a base class which is extending the Reusablepool. Here we are overriding the three methods for the creation, validation, and expiration of the object. This class will straightly get called by the client for requesting the new or reusable objects.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionPool extends ReusablePool<Connection> {

  private String url, username, password;

  public ConnectionPool(String driver, String url, String username, String password) {
    super();
    try {
      Class.forName(driver).newInstance();
    } catch (Exception e) {
      e.printStackTrace();
    }
    this.url = url;
    this.username = username;
    this.password = password;
  }

  @Override
  protected Connection createObject() {
    try {
      return (DriverManager.getConnection(url, username, password));
    } catch (SQLException e) {
      e.printStackTrace();
      return (null);
    }
  }

  @Override
  public void expiredObject(Connection o) {
    try {
      ((Connection) o).close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }

  @Override
  public boolean validateObject(Connection o) {
    try {
      return (!((Connection) o).isClosed());
    } catch (SQLException e) {
      e.printStackTrace();
      return (false);
    }
  }
}

Since we already have our pool class and the abstract class to manage the objects. Let’s create a client which is basically the main class just to call the objects, doing the required things over the database and release the objects if all the work is done. So that the connection object gets free to use by other clients as well.

package javadesignpatterns.creational.objectpoolpattern;

import java.sql.Connection;

public class Poolimplementationmain {

  public static void main(String[] args) {
    ConnectionPool reusablepool = new ConnectionPool("com.mysql.jdbc.Driver",
                  "jdbc:mysql://localhost:3306/dbname",
                  "usernname", "password");
    Connection con = reusablepool.getInstance();

    // Use Connection object as per the requirement(CRUD operation).
    reusablepool.releaseObject(con);

  }
}

Conclusion:

The Object Pools are usually implemented as Singletons class. I have given you an explanation of the object pool design pattern, let me know if you have any feedback on this.

By |Last Updated: May 9th, 2020|Categories: Java™|