1

Web アプリケーションで proxool 接続プールを使用して jdbc 接続を取得しようとしています。以下のコードは同じことを説明しています:

public static Connection getConnection(String key, boolean useConnectionPool, String poolName) {
    Connection connection = null;
    String alias = "DBCP" + poolName + "_" + key;
    String driverClass = "com.mysql.jdbc.Driver";
    checkAndLoadProps();
    String driverUrl = "jdbc:mysql://" + props.getProperty(key + "_DBMS_URL") + "/" + props.getProperty(key + "_DEF_SCHEMA") + "?autoReconnect=true&useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=false&rewriteBatchedStatement=true";
    String connectionPoolUrl = "proxool." + alias + ":" + driverClass + ":" + driverUrl;
    try {
        if (useConnectionPool) {
            info.remove("user");
            String user = props.getProperty(key + "_CLIENT");
            info.setProperty("user", user);
            info.remove("password");
            String password = props.getProperty(key + "_CLIENT_PASS");
            info.setProperty("password", password);
            String host = props.getProperty(key + "_DBMS_URL");

            synchronized (poolName) {
                connection = DriverManager.getConnection(connectionPoolUrl, info);
            }

        } 
        if (connection != null) {
            return connection;
        } else {
            System.out.println("DB Connection Not Established");
        }

    } catch (Exception ex) {
        System.out.println("DB Connection Not Established::" + ex.getMessage());
        ex.printStackTrace();
    }
    return null;
}

サーバーを起動するとすぐに、複数のスレッドがこのコードに並行してアクセスしようとし、同時変更例外がスローされます。

同期ブロックにクラスレベルのロックを提供することで修正できることを理解しています。しかし、それはパフォーマンスに深刻な影響を与えます。

これに対するより良い解決策はありますか?

4

1 に答える 1

1

info私にとって、あなたの問題は、明らかにそのインスタンスPropertiesが共有されていることに関連しています。javadoc に記載されているように、それを反復しながらその構造を変更すると、それPropertiesが拡張Hashtableされ、 an Hashtableがスローされる ことがわかっています。ConcurrentModificationException

イテレータの作成後に が構造的に変更された場合Hashtable、イテレータ自体の remove メソッド以外の方法で、イテレータは をスローし ConcurrentModificationExceptionます。

ここで、このメソッドを並行して呼び出す複数のスレッドがある場合、それらは同時にプロパティを削除して、あなたの構造を変更し、そのHashtable中でそれを反復処理しDriverManager.getConnection(connectionPoolUrl, info)て、ConcurrentModificationException.

あなたがすべきことは、スレッドセーフであり、同時に変更および反復できる に変換infoすることです。次に、次のように作成されたインスタンスConcurrentHashMap<Object, Object>を にパラメータとして指定します。DriverManager.getConnectionPropertiesinfo

private static Map<Object, Object> info = new ConcurrentHashMap<>();

public static Connection getConnection(String key, boolean useConnectionPool, 
    String poolName) {

    ...
    Properties properties = new Properties();
    properties.putAll(info);
    connection = DriverManager.getConnection(connectionPoolUrl, properties);
于 2016-11-29T14:59:24.013 に答える