Javaで接続プールを作成するコードが必要ですか?接続プールがすでに使用されている同じオブジェクトを返さないことをどのように確認しますか?クライアントが接続プールから取り出した後に接続を閉じた場合、どうなりますか?
これをSimple Javaの用語で作成し、マルチスレッド環境でどのように機能するかを確認したいと思います。どのメソッドが同期され、どのメソッドが同期されません。はいの場合、誰でもこのクラスにアクセスして接続プールを再初期化できますか?
以下のようなコードがあります。しかし、「プールからの接続を閉じるとプールに戻るのではなく、物理的に接続を閉じることはありません」。また、「接続がプールから借用されてまだ返されていない場合、「使用可能」ではなく、プールの別のクライアントに再配布できないため」と理解していませんでした。
import Java.util.*;
import Java.sql.*;
class ConnectionPoolManager
{
String databaseUrl = "jdbc:mysql://localhost:3306/myDatabase";
String userName = "userName";
String password = "userPass";
Vector connectionPool = new Vector();
public ConnectionPoolManager()
{
initialize();
}
public ConnectionPoolManager(
//String databaseName,
String databaseUrl,
String userName,
String password
)
{
this.databaseUrl = databaseUrl;
this.userName = userName;
this.password = password;
initialize();
}
private void initialize()
{
//Here we can initialize all the information that we need
initializeConnectionPool();
}
private void initializeConnectionPool()
{
while(!checkIfConnectionPoolIsFull())
{
System.out.println("Connection Pool is NOT full. Proceeding with adding new connections");
//Adding new connection instance until the pool is full
connectionPool.addElement(createNewConnectionForPool());
}
System.out.println("Connection Pool is full.");
}
private synchronized boolean checkIfConnectionPoolIsFull()
{
final int MAX_POOL_SIZE = 5;
//Check if the pool size
if(connectionPool.size() < 5)
{
return false;
}
return true;
}
//Creating a connection
private Connection createNewConnectionForPool()
{
Connection connection = null;
try
{
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(databaseUrl, userName, password);
System.out.println("Connection: "+connection);
}
catch(SQLException sqle)
{
System.err.println("SQLException: "+sqle);
return null;
}
catch(ClassNotFoundException cnfe)
{
System.err.println("ClassNotFoundException: "+cnfe);
return null;
}
return connection;
}
public synchronized Connection getConnectionFromPool()
{
Connection connection = null;
//Check if there is a connection available. There are times when all the connections in the pool may be used up
if(connectionPool.size() > 0)
{
connection = (Connection) connectionPool.firstElement();
connectionPool.removeElementAt(0);
}
//Giving away the connection from the connection pool
return connection;
}
public synchronized void returnConnectionToPool(Connection connection)
{
//Adding the connection from the client back to the connection pool
connectionPool.addElement(connection);
}
public static void main(String args[])
{
ConnectionPoolManager ConnectionPoolManager = new ConnectionPoolManager();
}
}
Javaで接続プールを作成するコードが必要ですか?
質問はわかりませんが、別の接続プールを作成しないでください。 C3P 、 Apache DBCP 、 Proxool または-のような既存のソリューションを使用してください BoneCP (そのフィールドの新しいプレイヤー)。 C3P0を使用します。
接続プールがすでに使用されている同じオブジェクトを返さないことをどのように確認しますか?
接続がプールから借用されてまだ返されていない場合、接続はプール内になく、プールの別のクライアントに割り当てることができないためです(リソースは返されるまでプールから削除されます)。
クライアントが接続プールから取り出した後に接続を閉じた場合、どうなりますか?
クライアントがプールから取得する接続は、実際には _Java.sql.Connection
_ ではなく、動作をカスタマイズする _Java.sql.Connection
_ のラッパー(プロキシ)ですいくつかのメソッドの。 close()
メソッドはそれらの1つであり、Connection
インスタンスをnot閉じますが、プールに返します。
自分で書いてはいけません。あなたのためにこれを行うオープンソースで使いやすいライブラリーがたくさんあり、自分で作ろうとして遭遇するすべての問題を解決します。
ApacheのCommons DBCPとCommons Poolを使用する簡単な例を次に示します。
最初にデータソースを設定します。
javax.sql.DataSource source = new org.Apache.commons.dbcp.BasicDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUsername("username");
source.setPassword("password");
source.setUrl("jdbc:mysql://localhost:3306/myDatabase");
データソースを取得したら、プールから簡単に接続を取得できます。
Java.sql.Connection connection = source.getConnection();
接続を閉じると、プールに戻されます。
connection.close();
このソースコードが役立つことを願っています http://jagadeeshmanne.blogspot.in/2014/03/connection-pool-in-Java-jdbc.html
Configuration.Java
package com.jmanne.utils;
public class Configuration {
public String DB_USER_NAME ;
public String DB_PASSWORD ;
public String DB_URL;
public String DB_DRIVER;
public Integer DB_MAX_CONNECTIONS;
public Configuration(){
init();
}
private static Configuration configuration = new Configuration();
public static Configuration getInstance(){
return configuration;
}
private void init(){
DB_USER_NAME = "root"
DB_PASSWORD = "root"
DB_URL = "jdbc:mysql://localhost:3306/jmanne"
DB_DRIVER = "com.mysql.jdbc.Driver"
DB_MAX_CONNECTIONS = 5
}
}
JdbcConnectionPool.Java
package com.jmanne.db;
import Java.sql.DriverManager;
import Java.sql.SQLException;
import Java.util.ArrayList;
import Java.util.List;
import com.jmanne.utils.Configuration;
import com.mysql.jdbc.Connection;
public class JdbcConnectionPool {
List<connection> availableConnections = new ArrayList<connection>();
public JdbcConnectionPool()
{
initializeConnectionPool();
}
private void initializeConnectionPool()
{
while(!checkIfConnectionPoolIsFull())
{
availableConnections.add(createNewConnectionForPool());
}
}
private synchronized boolean checkIfConnectionPoolIsFull()
{
final int MAX_POOL_SIZE = Configuration.getInstance().DB_MAX_CONNECTIONS;
if(availableConnections.size() < MAX_POOL_SIZE)
{
return false;
}
return true;
}
//Creating a connection
private Connection createNewConnectionForPool()
{
Configuration config = Configuration.getInstance();
try {
Class.forName(config.DB_DRIVER);
Connection connection = (Connection) DriverManager.getConnection(
config.DB_URL, config.DB_USER_NAME, config.DB_PASSWORD);
return connection;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public synchronized Connection getConnectionFromPool()
{
Connection connection = null;
if(availableConnections.size() > 0)
{
connection = (Connection) availableConnections.get(0);
availableConnections.remove(0);
}
return connection;
}
public synchronized void returnConnectionToPool(Connection connection)
{
availableConnections.add(connection);
}
}
DataSource.Java
package com.jmanne.db;
import Java.sql.SQLException;
import com.mysql.jdbc.Connection;
public class DataSource {
static JdbcConnectionPool pool = new JdbcConnectionPool();
public static Connection getConnection() throws ClassNotFoundException, SQLException{
Connection connection = pool.getConnectionFromPool();
return connection;
}
public static void returnConnection(Connection connection) {
pool.returnConnectionToPool(connection);
}
}
セマフォを使用するだけです。理想的には、接続プールとしてCP3O
またはDBCP
を使用する必要があります。これで、セマフォに基づいて接続を調整できます。
Get
を実行するたびに、SemaphoreからRelease
を取得してリリースします。セマフォ以上はスレッドセーフです。
既存のいずれかを使用します。 Apache DBCP
プールによって返される接続は、多くの場合、アプリケーションからのclose()
への呼び出しを「無視」するプロキシです。接続がプールに戻されると、再利用できます。また、プールは必要に応じて自動的に閉じて開き直します。
アプリケーションがサーバーで実行される場合、サーバーがプーリングを処理するデータソースとして設定するか、単純なJavaクライアントがApache DBCP(データベースへの場合)を使用するか、またはApache Commons Pooling APIここを参照してください: Apache Commons
独自のconnpoolをロールするための1つの引数は、回避される設定と追加のjarです。サードパーティのインターフェイスを有効にして、成熟したconnpoolに交換できるようにする必要があることに同意しますが、独自の小さなソリューションを用意することはできます。同期ブロックと、connを使用可能としてマークするclose()を使用したconnラッパーを使用したSelf Cleaning Vectorは、サーブレットアプリで非常にうまく機能します。
デフォルトサイズ10のプールの作成に役立つ接続プールユーティリティを作成するための同じ解決策が1つあります。
@Component public class ConnectionPool {private static final Logger logger = LoggerFactory.getLogger(ConnectionPool.class); private static final int MAX_POOL_SIZE_LIMIT = 10; private BlockingQueue activeConnectinoQueue = new LinkedBlockingQueue <>(); private BlockingQueue usedConnectinoList = new LinkedBlockingQueue <>(); private int initialPoolSize = 5;
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
public void initConnectionPool() {
logger.info("ConnectionPool initialization started.");
if(activeConnectinoQueue.isEmpty() && usedConnectinoList.isEmpty()) {
for (int i=0; i<initialPoolSize; i++) {
createConnections();
}
}
logger.info("ConnectionPool initialization completed. ConnectionPool size : {}", activeConnectinoQueue.size());
}
private void createConnections() {
try {
Connection connection = dataSource.getConnection();
activeConnectinoQueue.add(connection);
}catch (SQLException e) {
logger.error("Error in getting connection from pool : ", e);
}
}
public Connection getConnection() {
if(activeConnectinoQueue.isEmpty()) {
initConnectionPool();
}
Connection connection = activeConnectinoQueue.remove();
try {
if(connection.isClosed()) {
connection = dataSource.getConnection();
}
}catch (SQLException e) {
logger.error("Error while getting connection from pool : ", e);
}
usedConnectinoList.add(connection);
return connection;
}
public void releaseConnection(Connection connection) {
if(connection != null) {
usedConnectinoList.remove(connection);
activeConnectinoQueue.add(connection);
}
}
public void setInitialPoolSize(int initialPoolSize) {
if(!(initialPoolSize < 0 || initialPoolSize > MAX_POOL_SIZE_LIMIT)) {
this.initialPoolSize = initialPoolSize;
}
}
public int getInitialPoolSize() {
return initialPoolSize;
}
public int getConnectionPoolSize() {
return activeConnectinoQueue.size() + usedConnectinoList.size();
}
public void setDataSource(AbstractDataSource dataSource) {
this.dataSource = dataSource;
}
public void closeConnectionPool() {
logger.info("Closing connectionPool started.");
close(usedConnectinoList);
close(activeConnectinoQueue);
logger.info("ConnectionPool Closed.");
}
private void close(BlockingQueue<Connection> connectinosQueue) {
for (int i=0; i<connectinosQueue.size(); i++) {
Connection connection = connectinosQueue.remove();
if(connection != null) {
try {
connection.close();
} catch (SQLException e) {
logger.error("Error in initializing connection pool : ", e);
}
}
}
}
}
今それを安全にするために、ファクトリオブジェクトをアタッチする必要があります。
public enum ConnectionFactory {
CONNECTION;
private ConnectionPool connectionPool;
public void setConnectionPool(ConnectionPool connectionPool) {
this.connectionPool = connectionPool;
}
public Connection getConnection() {
return connectionPool.getConnection();
}
public void closeConnection() {
connectionPool.closeConnectionPool();
}
public void releaseConnection(Connection connection) {
connectionPool.releaseConnection(connection);
}
public int getConnectionPoolSize() {
return connectionPool.getConnectionPoolSize();
}
@Component
public static class ConnectionBuilder {
@Autowired
private ConnectionPool connectionPool;
public void setConnectionPool(ConnectionPool connectionPool) {
this.connectionPool = connectionPool;
}
@PostConstruct
public void postConstruct() {
for (ConnectionFactory cfactory : EnumSet.allOf(ConnectionFactory.class)) {
cfactory.setConnectionPool(connectionPool);
}
}
}
}