Creating objects (DB connections, threads, sockets) is expensive. Instead of creating and destroying them per request, maintain a pool of reusable objects. Borrow, use, return.
// ─── EXAMPLE 1 ──────────────────────────────────────────────────────────────
// WHAT WE ARE IMPLEMENTING:
// A database connection manager reusing a static set of heavy socket
// connections.
//
// WHERE THE PATTERN FITS IN:
// DatabaseConnectionPool acts as the Pool manager, tracking active and idle
// Connection client instances to throttle load.
// ────────────────────────────────────────────────────────────────────────────
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
// --- Pooled resource ---
class DatabaseConnection {
private final int id;
private boolean inUse = false;
public DatabaseConnection(int id) {
this.id = id;
System.out.println(" [Pool] Creating connection " + id);
}
public boolean query(String sql) {
if (!inUse) throw new IllegalStateException("Connection not checked out");
System.out.println(" [Conn " + id + "] Executing: " + sql);
return true;
}
void markInUse(boolean inUse) { this.inUse = inUse; }
}
// --- Object Pool ---
class ConnectionPool {
private final BlockingQueue<DatabaseConnection> available = new LinkedBlockingQueue<>();
private final AtomicInteger created = new AtomicInteger(0);
private final int maxSize;
public ConnectionPool(int maxSize) {
this.maxSize = maxSize;
// Pre-warm: create minimum connections
for (int i = 0; i < Math.min(3, maxSize); i++) {
available.add(createConnection());
}
}
private DatabaseConnection createConnection() {
return new DatabaseConnection(created.incrementAndGet());
}
public DatabaseConnection borrow() throws InterruptedException {
DatabaseConnection conn = available.poll();
if (conn == null) {
if (created.get() < maxSize) {
conn = createConnection();
} else {
// Wait for a connection to be returned (blocking)
conn = available.take();
}
}
conn.markInUse(true);
return conn;
}
public void release(DatabaseConnection conn) {
conn.markInUse(false);
available.offer(conn);
System.out.println(" [Pool] Connection " + conn + " returned to pool");
}
public int availableCount() { return available.size(); }
}
public class Main {
public static void main(String[] args) throws InterruptedException {
ConnectionPool pool = new ConnectionPool(5);
// Borrow and use
DatabaseConnection c1 = pool.borrow();
c1.query("SELECT * FROM users");
DatabaseConnection c2 = pool.borrow();
c2.query("INSERT INTO orders ...");
// Return to pool
pool.release(c1);
pool.release(c2);
System.out.println("Available connections: " + pool.availableCount());
}
}