Java Pooling Under High Concurrency: Resource Reuse and Performance Optimization
The article explains Java pooling techniques for high‑concurrency scenarios, introduces Apache Commons Pool 2, demonstrates how to configure dependencies, implement a PooledObjectFactory, create custom eviction policies and statistics, and shows a complete runnable example that highlights resource reuse and performance gains.
1. Introduction
Pooling technology pre‑allocates and centrally manages resources such as threads, connections, or memory, forming a resource pool for repeated use. This reduces the overhead of frequent creation and destruction, limits resource usage, and improves utilization.
2. Apache Commons Pool
Apache Commons Pool is a mature open‑source pooling framework that provides a standard object‑pool implementation. Version 2.0 rewrites the pooling mechanism, offering better performance, scalability, instance tracking, and monitoring.
3. Practical Example
3.1 Add Dependency
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.12.1</version>
</dependency>3.2 Object‑Pool Factory Interface
public interface PooledObjectFactory<T> {
void activateObject(PooledObject<T>);
void destroyObject(PooledObject<T>);
void destroyObject(PooledObject<T>, DestroyMode);
PooledObject<T> makeObject();
void passivateObject(PooledObject<T>);
boolean validateObject(PooledObject<T>);
}Key methods:
makeObject : called when a new instance is needed.
activateObject : invoked before borrowing an idle instance.
validateObject : checks whether an instance can be borrowed or returned.
passivateObject : called when returning an instance to the pool.
destroyObject : called when the instance is removed from the pool.
3.3 Custom Object Pool
public class Connection {
public void connect() { System.out.println("Connection established."); }
public void disconnect() { System.out.println("Connection closed."); }
}
public class ConnectionPooledObjectFactory extends BasePooledObjectFactory<Connection> {
@Override
public Connection create() { return new Connection(); }
@Override
public PooledObject<Connection> wrap(Connection conn) { return new DefaultPooledObject<>(conn); }
}3.4 Test Code
PooledObjectFactory<Connection> factory = new ConnectionPooledObjectFactory();
try (GenericObjectPool<Connection> objectPool = new GenericObjectPool<>(factory)) {
objectPool.setMinIdle(5);
objectPool.setMaxTotal(20);
objectPool.setMaxIdle(10);
Connection connection1 = objectPool.borrowObject();
connection1.connect();
System.err.println("object: %s".formatted(connection1.hashCode()));
Connection connection2 = objectPool.borrowObject();
connection2.connect();
System.err.println("object: %s".formatted(connection2.hashCode()));
objectPool.returnObject(connection2);
System.err.println("object: %s".formatted(connection2.hashCode()));
Connection connection3 = objectPool.borrowObject();
connection3.connect();
System.err.println("object: %s".formatted(connection3.hashCode()));
objectPool.returnObject(connection3);
}Output shows that the same underlying Connection instance can be reused after being returned to the pool.
4. Advanced Features
4.1 Custom Eviction Policy
public class PackEvictionPolicy implements EvictionPolicy<Connection> {
@Override
public boolean evict(EvictionConfig config, PooledObject<Connection> underTest, int idleCount) {
return config.getIdleSoftEvictDuration().compareTo(underTest.getIdleDuration()) < 0 &&
config.getMinIdle() < idleCount ||
config.getIdleEvictDuration().compareTo(underTest.getIdleDuration()) < 0;
}
}Configure the pool to use the custom policy:
GenericObjectPool<Connection> objectPool = new GenericObjectPool<>(factory);
objectPool.setEvictionPolicy(new PackEvictionPolicy());4.2 Statistics and Monitoring
The built‑in statistics allow monitoring of active and idle objects, borrowed count, and waiting threads.
System.err.println("""
Borrowed instances: %s
Idle instances: %s
Total borrowed: %s
Waiting threads: %s
""".formatted(
objectPool.getNumActive(),
objectPool.getNumIdle(),
objectPool.getBorrowedCount(),
objectPool.getNumWaiters()));Sample result:
Borrowed instances: 0
Idle instances: 2
Total borrowed: 3
Waiting threads: 05. Visual Flow
An illustration (image) shows the lifecycle of objects within the pool, from creation, activation, validation, passivation, to eviction.
The article concludes that using Apache Commons Pool 2 enables efficient resource reuse and performance optimization in high‑concurrency Java applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.
