Backend Development 8 min read

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.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Using Apache Commons GenericObjectPool for Process Pooling in Java

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.

backendJavaperformanceGenericObjectPoolpoolingApache Commons
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.