Cheap VPS & Xen Server


Residential Proxy Network - Hourly & Monthly Packages

Object Pool Pattern


Mostly, performance is the key issue during the software development and the object creation, which may be a costly step.

Object Pool Pattern says that ” to reuse the object that are expensive to create”.

Basically, an Object pool is a container which contains a specified amount of objects. 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 and destroy.

A pool helps to manage available resources in a better way. There are many using examples: especially in application servers there are data source pools, thread pools etc.

Advantage of Object Pool design pattern

  • It boosts the performance of the application significantly.
  • It is most effective in a situation where the rate of initializing a class instance is high.
  • It manages the connections and provides a way to reuse and share them.
  • It can also provide the limit for the maximum number of objects that can be created.

Usage:

  • When an application requires objects which are expensive to create. Eg: there is a need of opening too many connections for the database then it takes too longer to create a new one and the database server will be overloaded.
  • When there are several clients who need the same resource at different times.

NOTE: Object pool design pattern is essentially used in Web Container of the server for creating thread pools and data source pools to process the requests.


Example of Object Pool Pattern:

Let’s understand the example by the given UML diagram.

UML for Object Pool Pattern

objectpooluml

Implementation of above UML:

Step 1

Create an ObjectPool class that is used to create the number of objects.

File: ObjectPool.java
  1. import java.util.concurrent.ConcurrentLinkedQueue;
  2. import java.util.concurrent.Executors;
  3. import java.util.concurrent.ScheduledExecutorService;
  4. import java.util.concurrent.TimeUnit;
  5. public abstract class ObjectPool<T> {
  6. /*
  7.   pool implementation is based on ConcurrentLinkedQueue from the java.util.concurrent package.
  8.   ConcurrentLinkedQueue is a thread-safe queue based on linked nodes. 
  9.    Because the queue follows FIFO technique (first-in-first-out).
  10.  */
  11.    private ConcurrentLinkedQueue<T> pool;
  12.  /* 
  13.   
  14.    ScheduledExecutorService starts a special task in a separate thread and observes
  15.    the minimum and maximum number of objects in the pool periodically in a specified 
  16.     time (with parameter validationInterval). 
  17.    When the number of objects is less than the minimum, missing instances will be created. 
  18.    When the number of objects is greater than the maximum, too many instances will be removed. 
  19.    This is sometimes useful for the balance of memory consuming objects in the pool.
  20. */
  21.     private ScheduledExecutorService executorService;
  22.        /*
  23.      * Creates the pool.
  24.      *
  25.      * @param minObjects : the minimum number of objects residing in the pool
  26.      */
  27.     public ObjectPool(final int minObjects)
  28.     {
  29.         // initialize pool
  30.         initialize(minObjects);
  31.     }
  32.     /*
  33.       Creates the pool.
  34.       @param minObjects:   minimum number of objects residing in the pool.
  35.       @param maxObjects:   maximum number of objects residing in the pool.
  36.       @param validationInterval: time in seconds for periodical checking of 
  37.          minObjects / maxObjects conditions in a separate thread.
  38.       When the number of objects is less than minObjects, missing instances will be created.
  39.       When the number of objects is greater than maxObjects, too many instances will be removed.
  40.     */
  41.      public ObjectPool(final int minObjects, final int maxObjects, final long validationInterval) {
  42.         // initialize pool
  43.          initialize(minObjects);
  44.           // check pool conditions in a separate thread
  45.         executorService = Executors.newSingleThreadScheduledExecutor();
  46.         executorService.scheduleWithFixedDelay(new Runnable()  // annonymous class
  47.         {
  48.             @Override
  49.             public void run() {
  50.                 int size = pool.size();
  51.                 if (size < minObjects) {
  52.                     int sizeToBeAdded = minObjects + size;
  53.                     for (int i = 0; i < sizeToBeAdded; i++) {
  54.                         pool.add(createObject());
  55.                     }
  56.                 } else if (size > maxObjects) {
  57.                     int sizeToBeRemoved = size – maxObjects;
  58.                     for (int i = 0; i < sizeToBeRemoved; i++) {
  59.                         pool.poll();
  60.                     }
  61.                 }
  62.             }
  63.         }, validationInterval, validationInterval, TimeUnit.SECONDS);
  64.     }
  65.   /*
  66.       Gets the next free object from the pool. If the pool doesn’t contain any objects,
  67.       a new object will be created and given to the caller of this method back.
  68.      
  69.       @return T borrowed object
  70.   */
  71.     public T borrowObject() {
  72.         T object;
  73.         if ((object = pool.poll()) == null)
  74.         {
  75.             object = createObject();
  76.         }
  77.         return object;
  78.     }
  79.  /*
  80.       Returns object back to the pool.
  81.       @param object object to be returned
  82.   */
  83.     public void returnObject(T object) {
  84.         if (object == null) {
  85.             return;
  86.         }
  87.         this.pool.offer(object);
  88.     }
  89.    /*
  90.         Shutdown this pool.
  91.     */
  92.       public void shutdown(){
  93.         if (executorService != null){
  94.             executorService.shutdown();
  95.         }
  96.     }
  97.     /*
  98.         Creates a new object.
  99.          @return T new object
  100.      */
  101.     protected abstract T createObject();
  102.     private void initialize(final int minObjects)  {
  103.         pool = new ConcurrentLinkedQueue<T>();
  104.         for (int i = 0; i < minObjects; i++) {
  105.             pool.add(createObject());
  106.         }
  107.     }
  108. }// End of the ObjectPool Class.

Step 2

Create an ExportingProcess class that will be used by ExportingTask class.

File: ExportingProcess.java
  1. public class ExportingProcess {
  2.  private long processNo;
  3.     public ExportingProcess(long processNo)  {
  4.          this.processNo = processNo;
  5.         // do some  expensive calls / tasks here in future
  6.         // ………
  7.       System.out.println(“Object with process no. “ + processNo + ” was created”);
  8.      }
  9.     public long getProcessNo() {
  10.         return processNo;
  11.     }
  12. }// End of the ExportingProcess class.

Step 3

Create an ExportingTask class that will use ExportingProcess and ObjectPool class.

File: ExportingTask.java
  1. public class ExportingTask implements Runnable {
  2.         private ObjectPool<ExportingProcess> pool;
  3.         private int threadNo;
  4.         public ExportingTask(ObjectPool<ExportingProcess> pool, int threadNo){
  5.             this.pool = pool;
  6.             this.threadNo = threadNo;
  7.         }
  8.         public void run() {
  9.             // get an object from the pool
  10.             ExportingProcess exportingProcess = pool.borrowObject();
  11.             System.out.println(“Thread “ + threadNo + “: Object with process no. “
  12.                     + exportingProcess.getProcessNo() + ” was borrowed”);
  13.             //you can  do something here in future
  14.             // ………
  15.                // return ExportingProcess instance back to the pool
  16.             pool.returnObject(exportingProcess);
  17.             System.out.println(“Thread “ + threadNo +“: Object with process no. “
  18.                    + exportingProcess.getProcessNo() + ” was returned”);
  19.         }
  20.     }// End of the ExportingTask class. 

Step 4

Create an ObjectPoolDemo class.

File: ObjectPoolDemo.java
  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. import java.util.concurrent.TimeUnit;
  4. import java.util.concurrent.atomic.AtomicLong;
  5. public class ObjectPoolDemo{
  6.       private ObjectPool<ExportingProcess> pool;
  7.       private AtomicLong processNo=new AtomicLong(0);
  8.       public void setUp() {
  9.             // Create a pool of objects of type ExportingProcess.
  10.            /*Parameters:
  11.              1) Minimum number of special ExportingProcess instances residing in the pool = 4
  12.              2) Maximum number of special ExportingProcess instances residing in the pool = 10
  13.              3) Time in seconds for periodical checking of minObjects / maxObjects conditions
  14.                 in a separate thread = 5.
  15.              –>When the number of ExportingProcess instances is less than minObjects, 
  16.                  missing instances will be created.
  17.              –>When the number of ExportingProcess instances is greater than maxObjects,
  18.                   too many instances will be removed.
  19.             –>If the validation interval is negative, no periodical checking of 
  20.                   minObjects / maxObjects conditions in a separate thread take place.
  21.               These boundaries are ignored then.
  22.            */
  23.       pool = new ObjectPool<ExportingProcess>(4105)
  24.         {
  25.             protected ExportingProcess createObject()
  26.             {
  27.                 // create a test object which takes some time for creation
  28.                 return new ExportingProcess( processNo.incrementAndGet());
  29.             }
  30.         };
  31.     }
  32.     public void tearDown() {
  33.         pool.shutdown();
  34.     }
  35.     public void testObjectPool() {
  36.         ExecutorService executor = Executors.newFixedThreadPool(8);
  37.         // execute 8 tasks in separate threads
  38.         executor.execute(new ExportingTask(pool, 1));
  39.         executor.execute(new ExportingTask(pool, 2));
  40.         executor.execute(new ExportingTask(pool, 3));
  41.         executor.execute(new ExportingTask(pool, 4));
  42.         executor.execute(new ExportingTask(pool, 5));
  43.         executor.execute(new ExportingTask(pool, 6));
  44.         executor.execute(new ExportingTask(pool, 7));
  45.         executor.execute(new ExportingTask(pool, 8));
  46.         executor.shutdown();
  47.         try {
  48.             executor.awaitTermination(30, TimeUnit.SECONDS);
  49.             } catch (InterruptedException e)
  50.               {
  51.                e.printStackTrace();
  52.               }
  53.     }
  54.     public static void main(String args[])  {
  55.         ObjectPoolDemo op=new ObjectPoolDemo();
  56.         op.setUp();
  57.         op.tearDown();
  58.         op.testObjectPool();
  59.    }
  60. }//End of the ObjectPoolDemo class.

download this Object Pool Pattern Example

Output

objectpooloutput

Comments

comments