Build your own
ObjectPool in Java to boost app speed -
JavaWorld - June
1998
Tutorial Details:
Build your own ObjectPool in Java to boost app speed
Build your own ObjectPool in Java to boost app speed
By: By Thomas E. Davis
Increase the speed of your applications while reducing memory requirements
hen I first implemented object pooling (specifically for database connections) into a realtime, multiuser application, average transaction times dropped from 250 milliseconds to 30 milliseconds. Users actually noticed and commented on the drastic increase in performance.
The idea of object pooling is similar to the operation of your local library. When you want to read a book, you know that it's cheaper to borrow a copy from the library rather than purchase your own copy. Likewise, it is cheaper (in relation to memory and speed) for a process to borrow an object rather than create its own copy. In other words, the books in the library represent objects and the library patrons represent the processes. When a process needs an object, it checks out a copy from an object pool rather than instantiate a new one. The process then returns the object to the pool when it is no longer needed.
There are, however, a few minor distinctions between object pooling and the library analogy that should be understood. If a library patron wants a particular book, but all the copies of that book are checked out, the patron must wait until a copy is returned. We don't ever want a process to have to wait for an object, so the object pool will instantiate new copies as necessary. This could lead to an exhoribitant amount of objects lying around in the pool, so it will also keep a tally on unused objects and clean them up periodically.
My object pool design is generic enough to handle storage, tracking, and expiration times, but instantiation, validation, and destruction of specific object types must be handled by subclassing.
Now that the basics out of the way, lets jump into the code. This is the skeletal object:
public abstract class ObjectPool
{
private long expirationTime;
private Hashtable locked, unlocked;
abstract Object create();
abstract boolean validate( Object o );
abstract void expire( Object o );
synchronized Object checkOut(){...}
synchronized void checkIn( Object o ){...}
}
Internal storage of the pooled objects will be handled with two Hashtable objects, one for locked objects and the other for unlocked. The objects themselves will be the keys of the hashtable and their last-usage time (in epoch milliseconds) will be the value. By storing the last time an object was used, the pool can expire it and free up memory after a specied duration of inactivity.
Ultimately, the object pool would allow the subclass to specify the initial size of the hashtables along with their growth rate and the expiration time, but I'm trying to keep it simple for the purposes of this article by hard-coding these values in the constructor.
ObjectPool()
{
expirationTime = 30000; // 30 seconds
locked = new Hashtable();
unlocked = new Hashtable();
}
The checkOut() method first checks to see if there are any objects in the unlocked hashtable. If so, it cycles through them and looks for a valid one. Validation depends on two things. First, the object pool checks to see that the object's last-usage time does not exceed the expiration time specified by the subclass. Second, the object pool calls the abstract validate() method, which does any class-specific checking or reinitialization that is needed to re-use the object. If the object fails validation, it is freed and the loop continues to the next object in the hashtable. When an object is found that passes validation, it is moved into the locked hashtable and returned to the process that requested it. If the unlocked hashtable is empty, or none of its objects pass validation, a new object is instantiated and returned.
synchronized Object checkOut()
{
long now = System.currentTimeMillis();
Object o;
if( unlocked.size() > 0 )
{
Enumeration e = unlocked.keys();
while( e.hasMoreElements() )
{
o = e.nextElement();
if( ( now - ( ( Long ) unlocked.get( o ) ).longValue() ) >
expirationTime )
{
// object has expired
unlocked.remove( o );
expire( o );
o = null;
}
else
{
if( validate( o ) )
{
unlocked.remove( o );
locked.put( o, new Long( now ) );
return( o );
}
else
{
// object failed validation
unlocked.remove( o );
expire( o );
o = null;
}
}
}
}
// no objects available, create a new one
o = create();
locked.put( o, new Long( now ) );
return( o );
}
That's the most complex method in the ObjectPool class, it's all downhill from here. The checkIn() method simply moves the passed-in object from the locked hashtable into the unlocked hashtable.
synchronized void checkIn( Object o )
{
locked.remove( o );
unlocked.put( o, new Long( System.currentTimeMillis() ) );
}
The three remaining methods are abstract and therefore must be implemented by the subclass. For the sake of this article, I am going to create a database connection pool called JDBCConnectionPool. Here's the skeleton:
public class JDBCConnectionPool extends ObjectPool
{
private String dsn, usr, pwd;
public JDBCConnectionPool(){...}
create(){...}
validate(){...}
expire(){...}
public Connection borrowConnection(){...}
public void returnConnection(){...}
}
The JDBCConnectionPool will require the application to specify the database driver, DSN, username, and password upon instantiation (via the constructor). If this is Greek to you, don't worry, JDBC is another topic. Just bear with me until we get back to the pooling.
public JDBCConnectionPool( String driver, String dsn, String usr, String pwd )
{
try
{
Class.forName( driver ).newInstance();
}
catch( Exception e )
{
e.printStackTrace();
}
this.dsn = dsn;
this.usr = usr;
this.pwd = pwd;
}
Now we can dive into implementation of the abstract methods. As you saw in the checkOut() method, ObjectPool will call create() from its subclass when it needs to instantiate a new object. For JDBCConnectionPool, all we have to do is create a new Connection object and pass it back. Again, for the sake of keeping this article simple, I am throwing caution to the wind and ignoring any exceptions and null-pointer conditions.
Object create()
{
try
{
return( DriverManager.getConnection( dsn, usr, pwd ) );
}
catch( SQLException e )
{
e.printStackTrace();
return( null );
}
}
Before the ObjectPool frees an expired (or invalid) object for garbage collection, it passes it to its subclassed expire() method for any necessary last-minute clean-up (very similar to the finalize() method called by the garbage collector). In the case of JDBCConnectionPool, all we need to do is close the connection.
void expire( Object o )
{
try
{
( ( Connection ) o ).close();
}
catch( SQLException e )
{
e.printStackTrace();
}
}
And finally, we need to implement the validate() method that ObjectPool calls to make sure an object is still valid for use. This is also the place that any re-initialization should take place. For JDBCConnectionPool, we just check to see that the connection is still open.
boolean validate( Object o )
{
try
{
return( ! ( ( Connection ) o ).isClosed() );
}
catch( SQLException e )
{
e.printStackTrace();
return( false );
}
}
That's it for internal functionality. JDBCConnectionPool will allow the application to borrow and return database connections via these incredibly simple and aptly named methods.
public Connection borrowConnection()
{
return( ( Connection ) super.checkOut() );
}
public void returnConnection( Connection c )
{
super.checkIn( c );
}
This design has a couple of flaws. Perhaps the biggest is the possibility of creating a large pool of objects that never gets released. For example, if a bunch of processes request an object from the pool simultaneously, the pool will create all the instances necessary. Then, if all the processes return the objects back to the pool, but checkOut() never gets called again, none of the objects get cleaned up. This is a rare occurrence for active applications, but some back-end processes that have "idle" time might produce this scenario. I solved this design problem with a "clean up" thread, but I'll save that discussion for a follow-up article. I will also cover the proper handling of errors and propagation of exceptions to make the pool more robust for mission-critical applications.
I welcome any comments, criticisms, and/or design improvements you may have to offer.
This page formated for crawlers and browsers that don't support scripts and tables.
Home
EZone
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: Build your own
ObjectPool in Java to boost app speed -
JavaWorld - June
1998
View Tutorial: Build your own
ObjectPool in Java to boost app speed -
JavaWorld - June
1998
Related
Tutorials:
Enhance your Java application with Java Native Interface (JNI)
Enhance your Java application with Java Native Interface (JNI) |
XSLT blooms with
Java
XSLT blooms with
Java |
Boost Struts with
Boost Struts with XSLT and XML |
Best tools for
mobile application development
Best tools for
mobile application development |
J2ME devices:
Real-world performance
J2ME devices:
Real-world performance |
Profiling CPU
usage from within a Java application
Profiling CPU
usage from within a Java application |
JHome
JHome
Automation Light Interface Control Environment aka A.L.I.C.E. is written as a 100% Java application using both Swing and Comm API packages, all of which are extensions to the Java core libraries. Alice will allow you to control your X10 enabled li |
Worth
reading
Worth
reading |
JXMLAppKit 2.0
JXMLAppKit is a pure Swing java framework for editing an XML document with multiple XML editors. |
Improve Application Management With JMX
Improve Application Management With JMX
Leverage JMX technology and existing tools to boost the operations management capabilities of your business applications.
|
JGraph - The Java Graph Diagram Component
JGraph - The Java Graph Diagram Component
JGraphAddons is a drop-in functional module that adds powerful and configurable layout algorithms to your existing JGraphs. They include hierarchical, circular and tree layouts capable of giving your JGraph app |
Writing Ant Tasks
Writing Ant Tasks
A nice feature of Ant is that it is designed to allow you to add your own tasks and use them in an build. This article shows you the basics of writing an Ant task and how to get a task to work. |
new
Version 0.9.3 of the Quake2 Java port Jake2
With the new Jake2 release 0.9.3 savegames are working. So you can take a break on your mission.
|
Annotations in Tiger, Part 2: Custom annotations
Write your own annotations in Java 5
Part 1 of this series introduced annotations, the new metadata facility in J2SE 5.0, and focused on Tiger's basic built-in annotations. A more powerful related feature is support for writing your own annotations. In t |
Encapsulate reusable functionality in JSP tags
JavaServer Pages (JSP) are a great mechanism for delivering dynamic Web-based content. JSP provides a set of predefined tags, but you can also define your own tag extensions that encapsulate common functionality. |
JDBC RowSet Implementations Tutorial (PDF)
This tutorial explains how to use the standard JDBC RowSet implementations that are provided as part of J2SE 5.0. Get up to speed with each RowSet definition and benefit from improved scalability and robustness. |

Free Web Site Hosting Services include "hostsearchbox.php"; ?>
Below is the listing of the hosting providers providing free web hosting services. These services helps you building your sites even if you have no experience in HTML writing.
Zero |
Introduction To Enterprise Java Bean(EJB). Developing web component.
Introduction To Enterprise Java Bean(EJB). Developing web component.
Developing web component
Introduction To Java Beans
J2EE specification defines the structure of a J2EE application. According to the specification J2EE application consists of |
Building Web Application With Ant and Deploying on Jboss 3.0
Building Web Application With Ant and Deploying on Jboss 3.0
Building Web Application With Ant and Deploying on Jboss 3.0
Previous Tutorial Index Next
In this lesson I will show you how to build you web application and install on the Jboss 3.0 |
developing a Session Bean and a Servlet and deploy the web application on
JBoss 3.0
developing a Session Bean and a Servlet and deploy the web application on JBoss 3.0
Writing Stateless Session Bean and Calling through Servlet
Previous Tutorial Index Next
In this lesson I will show you how to develop a Stateless Session Bean and |
|
|
|