Шаблон проектирования объектный пул на Java
Объектный пул (англ. object pool) — порождающий шаблон проектирования, набор инициализированных и готовых к использованию объектов. Когда системе требуется объект, он не создаётся, а берётся из пула. Когда объект больше не нужен, он не уничтожается, а возвращается в пул.
Паттерн объектный пул обычно используется в случаях, где вызов объектов является дорогостоящим, а объекты можно эффективно использовать повторно. К числу таких примеров относятся:
1. Соединения с базами данных: Управление пулом соединений с базами данных позволяет повысить производительность приложений, взаимодействующих с базами данных.
2. Пул потоков: в многопоточных приложениях повторное использование потоков из пула потоков позволяет избежать накладных расходов на создание новых потоков для каждой задачи.
3. Сетевые соединения: В сетевом программировании управление пулом сетевых соединений может привести к более эффективному использованию ресурсов.
Теперь рассмотрим пример использования паттерна в Java для создания простого пула объектов Connection.
В этом примере (смотри картинку) мы создали простой класс `ConnectionPool` для управления пулом соединений с базой данных. При создании объекта `ConnectionPool` пул инициализируется с заданным количеством соединений. Клиенты могут запрашивать соединения из пула с помощью метода `getConnection()` и освобождать их обратно в пул с помощью метода releaseConnection(), когда они закончили их использовать.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
public class ConnectionPool {
private final LinkedList<Connection> pool;
private final String url;
private final String username;
private final String password;
private final int poolSize;
public ConnectionPool(String url, String username, String password, int poolSize) {
this.pool = new LinkedList<>();
this.url = url;
this.username = username;
this.password = password;
this.poolSize = poolSize;
initializePool();
}
private void initializePool() {
try {
Class.forName("com.mysql.jdbc.Driver");
for (int i = 0; i < poolSize; i++) {
Connection connection = DriverManager.getConnection(url, username, password);
pool.add(connection);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
public Connection getConnection() {
if (pool.isEmpty()) {
System.out.println("Pool is empty. Waiting for a connection...");
return null; // In a real-world scenario, you would typically wait until a connection is available.
}
return pool.removeFirst();
}
public void releaseConnection(Connection connection) {
pool.addLast(connection);
}
public void closeAllConnections() throws SQLException {
for (Connection connection : pool) {
connection.close();
}
pool.clear();
}
}
// Usage example:
public class Main {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "root";
String password = "password";
int poolSize = 5;
ConnectionPool connectionPool = new ConnectionPool(url, username, password, poolSize);
// Get a connection from the pool
Connection connection1 = connectionPool.getConnection();
// Use the connection...
// Release the connection back to the pool
connectionPool.releaseConnection(connection1);
// Close all connections and clean up the pool when it's no longer needed
try {
connectionPool.closeAllConnections();
} catch (SQLException e) {
e.printStackTrace();
}
}
}