Using Apache Commons GenericObjectPool for Process Pooling in Java
This article explains how Java developers can leverage Apache Commons Pool's GenericObjectPool to implement custom process pooling, covering the required factory interface, configuration options, and practical code examples for creating, borrowing, and returning pooled process objects to improve performance.
Some Introduction
As a Java developer, pooling techniques such as thread pools and connection pools are commonly used, and Java provides mature tools for these purposes.
When a thread pool is needed, Spring's ThreadPoolTaskExecutor is often chosen, which manages thread lifecycles and task states.
Thread Pool Operation Diagram
Body Starts
In the author's scenario, a Java service launches a special process via command line and destroys it after use; because startup time is sensitive, a process pool is introduced to reuse processes and reduce latency.
Understanding GenericObjectPool
The concept of pooling is familiar, but implementing a custom pool from scratch can be difficult. Apache Commons Pool provides GenericObjectPool , which assists in building custom object pools; for example, JedisPool is built with it.
The constructor of GenericObjectPool takes three parameters, with only PooledObjectFactory being mandatory.
/**
* Creates a new {@code GenericObjectPool} that tracks and destroys
* objects that are checked out, but never returned to the pool.
*
* @param factory The object factory to be used to create object instances
* used by this pool
* @param config The base pool configuration to use for this pool instance.
* The configuration is used by value. Subsequent changes to
* the configuration object will not be reflected in the
* pool.
* @param abandonedConfig Configuration for abandoned object identification
* and removal. The configuration is used by value.
*/
public GenericObjectPool(final PooledObjectFactory
factory,
final GenericObjectPoolConfig
config, final AbandonedConfig abandonedConfig)
{ }PooledObjectFactory is responsible for creating, validating, activating, and destroying pooled objects.
void activateObject(PooledObject
p) throws Exception;
void destroyObject(PooledObject
p) throws Exception;
PooledObject
makeObject() throws Exception;
void passivateObject(PooledObject
p) throws Exception;
boolean validateObject(PooledObject
p);For detailed API documentation, refer to the GenericObjectPool Javadoc.
Using GenericObjectPool
First, add the Maven dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${version}</version>
</dependency>Implement PooledObjectFactory for your specific object. Below is an example for a process pool:
public class MyProcessFactory implements PooledObjectFactory
{
@Override
public void destroyObject(PooledObject
p) throws Exception {
final MyProcess process = p.getObject();
if (null != process) {
// destroy process
process.stop();
}
}
@Override
public PooledObject
makeObject() throws Exception {
// create a new process
MyProcess process = new MyProcess();
process.start();
return new DefaultPooledObject<>(process);
}
// other methods can be implemented as needed
}Then build the pool instance:
PooledObjectFactory
factory = new MyProcessFactory();
GenericObjectPool
pool = new GenericObjectPool(factory);Borrow and return objects:
// acquire a process instance
MyProcess process = pool.borrowObject();
// return the instance
pool.returnObject(process);Advanced Usage with GenericObjectPoolConfig
GenericObjectPoolConfig configures core parameters such as max total, max idle, min idle, etc., inherited from BaseObjectPoolConfig which also controls eviction policies and LIFO behavior.
/**
* The default value for the {@code maxTotal} configuration attribute.
*/
public static final int DEFAULT_MAX_TOTAL = 8;
/**
* The default value for the {@code maxIdle} configuration attribute.
*/
public static final int DEFAULT_MAX_IDLE = 8;
/**
* The default value for the {@code minIdle} configuration attribute.
*/
public static final int DEFAULT_MIN_IDLE = 0;Example configuration to keep four processes permanently:
private GenericObjectPoolConfig
genericObjectPoolConfig() {
final GenericObjectPoolConfig
config = new GenericObjectPoolConfig<>();
config.setMaxTotal(20); // maximum pool size
config.setMaxIdle(4); // maximum idle objects
config.setMinIdle(0); // minimum idle objects
config.setMaxWait(Duration.ofSeconds(5));
config.setTimeBetweenEvictionRuns(Duration.ofMinutes(1));
config.setMinEvictableIdleTime(Duration.ofMinutes(10));
config.setTestOnBorrow(true);
config.setLifo(false);
return config;
}Conclusion
The article covers the essential steps to build and configure a custom object pool using Apache Commons Pool, demonstrating how to achieve performance improvements by reusing expensive resources such as external processes.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.