본문 바로가기

Dev.../플밍 관련 자료

[펌] Jakarta Commons Pool

<출처 : jakarta.apache.org>

The Pool Component

Pool provides an Object-pooling API, with three major aspects:

  1. A generic object pool interface that clients and implementors can use to provide easily interchangable pooling implementations.
  2. A toolkit for creating modular object pools.
  3. Several general purpose pool implementations.

Releases

See the downloads page for information on obtaining releases.

Features

The org.apache.commons.pool package defines a handful of pooling interfaces and some base classes that may be useful when creating new pool implementations.

ObjectPool

ObjectPool defines a trivially simple pooling interface:

public interface ObjectPool {    Object borrowObject();    void returnObject(Object borrowed);}

Some client classes won't integrate with Pool any more than this. Clients written to this interface can use arbitrary ObjectPool implementations interchangeably.

BaseObjectPool provides an abstract base implementation of ObjectPool. Clients are encouraged but not required to extend BaseObjectPool for new ObjectPool implementations.

KeyedObjectPool defines a similiar interface for pools composed of heterogenous objects:

public interface KeyedObjectPool {    Object borrowObject(Object key);    void returnObject(Object key, Object borrowed);}

PoolableObjectFactory

The Pool package makes it possible separate the way in which instances are pooled from the way in which instances are created and destroyed. PoolableObjectFactory supports this by providing a generic inteface for the lifecycle of a pooled object:

public interface PoolableObjectFactory {    Object makeObject();    void activateObject(Object obj);    void passivateObject(Object obj);    boolean validateObject(Object obj);    void destroyObject(Object obj);}

ObjectPool implementations may be written to accept arbitrary PoolableObjectFactorys. This makes is possible for clients to select pooling-behavior distinct from the kinds of objects that are pooled.

BasePoolableObjectFactory provides an abstract base implementation of PoolableObjectFactory that makes implementations a snap.

KeyedPoolableObjectFactory defines a similiar interface for KeyedObjectPools:

public interface KeyedPoolableObjectFactory {    Object makeObject(Object key);    void activateObject(Object key, Object obj);    void passivateObject(Object key, Object obj);    boolean validateObject(Object key, Object obj);    void destroyObject(Object key, Object obj);}

BaseKeyedPoolableObjectFactory provides an abstract base implementation of KeyedPoolableObjectFactory that makes implementations a snap.

The org.apache.commons.pool.impl package provides some Pool implementations.

StackObjectPool

StackObjectPool will pool a finite number of "idle" instances, but will create new instances a needed in order to support high demand.

StackKeyedObjectPool offers the same behavior for keyed pools.

GenericObjectPool

GenericObjectPool provides a wide variety of configuration options, including the ablity to cap the number of idle or active instances, to evict instances as they sit idle in the pool, etc.

GenericKeyedObjectPool offers the same behavior for keyed pools.

SoftReferenceObjectPool

SoftReferenceObjectPool can grow as needed, but allows the garbage collector to evict idle instances from the pool as needed.

 

 

ObjectPool



ObjectPool defines a simple pooling interface.

  • GenericObjectPool : ObjectPool implementation with a FIFO (First In First Out) behavior. This queue like behavior makes sure each object is regularly used. (helps preventing time-outs)
  • StackObjectPool : ObjectPool implementation with a LIFO (Last In First Out) behavior.
  • SoftReferenceObjectPool : ObjectPool implementation with a LIFO (Last In First Out) behavior. Additionally this pool wraps each object in a SoftReference allowing the garbage collector to remove them in response to memory demand.

KeyedObjectPool



A KeyedObjectPool pools instances of multiple types. Each type may be accessed using an arbitrary key.

 

GenericObjectPool

GenericKeyedObjectPool

 
 
 
 
 
 
 
 

A Simple Pool Client

Suppose you're writing a set of java.io.Reader utilities, and would like to provide a method for dumping the contents of a Reader to a String. Here's the code for the ReaderUtil, implemented without an ObjectPool:

import java.io.Reader; import java.io.IOException;  public class ReaderUtil {     public ReaderUtil() {     }      /**      * Dumps the contents of the {@link Reader} to a      * String, closing the {@link Reader} when done.      */     public String readToString(Reader in) throws IOException {         StringBuffer buf = new StringBuffer();         try {             for(int c = in.read(); c != -1; c = in.read()) {                 buf.append((char)c);             }             return buf.toString();         } catch(IOException e) {             throw e;         } finally {             try {                 in.close();             } catch(Exception e) {                 // ignored             }         }     } }

For the sake of this example, let's assume we want to to pool the StringBuffers used to buffer the Reader's contents. (A pool of StringBuffers may or may not be useful in practice. We're just using it as a simple example here.)

Let's further assume that a complete pool implementation will be provided via a constructor. (We'll show you how to create such an implementation in just a moment.) Then to use the pool we simply call borrowObject to obtain the buffer, and then call returnObject when we're done with it. Then a ReaderUtil implementation using a pool of StringBuffers might look like this:

import org.apache.commons.pool.ObjectPool;import java.io.Reader; import java.io.IOException;  public class ReaderUtil {     private ObjectPool pool;     public ReaderUtil(ObjectPool pool) {         this.pool = pool;    }      /**      * Dumps the contents of the {@link Reader} to a      * String, closing the {@link Reader} when done.      */     public String readToString(Reader in) throws IOException {         StringBuffer buf = null;        try {             buf = (StringBuffer)(pool.borrowObject());            for(int c = in.read(); c != -1; c = in.read()) {                 buf.append((char)c);             }             return buf.toString();         } catch(IOException e) {             throw e;         } catch(Exception e) {            throw new RuntimeException("Unable to borrow buffer from pool" +                     e.toString());        } finally {             try {                 in.close();             } catch(Exception e) {                 // ignored             }             try {                if(null != buf) {                    pool.returnObject(buf);                }            } catch(Exception e) {                // ignored            }        }     } }

Since we've constrained ourselves to the ObjectPool interface, an arbitrary pool implementation (returning, in our case, StringBuffers) can be used. When a different or "better" pool implemenatation comes along, we can simply drop it into our ReaderUtil without changing a line of code.

A PoolableObjectFactory

Recall that Pool provides a simple toolkit for creating object pools. The PoolableObjectFactory interface is an important part of this toolkit. PoolableObjectFactory defines lifecycle methods for pooled objects. We can use it to separate the kinds of objects that are pooled and how they are created, persisted, or destroyed, from the pooling algorithm itself.

Suppose we have an ObjectPool implementation that accepts a PoolableObjectFactory (for example, any of the implementations in the org.apache.commons.pool.impl package). Then we need only provide the factory implemenation in order to pool a new kind of object.

Here's a PoolableObjectFactory implementation that creates StringBuffers as used above.

import org.apache.commons.pool.BasePoolableObjectFactory;  public class StringBufferFactory extends BasePoolableObjectFactory {     // for makeObject we'll simply return a new buffer     public Object makeObject() {         return new StringBuffer();     }          // when an object is returned to the pool,      // we'll clear it out     public void passivateObject(Object obj) {         StringBuffer buf = (StringBuffer)obj;         buf.setLength(0);     }          // for all other methods, the no-op      // implementation in BasePoolableObjectFactory     // will suffice }

We can, for example, use this factory with the StackObjectPool to instantiate our ReaderUtil as follows:

new ReaderUtil(new StackObjectPool(new StringBufferFactory()))