使用连接池时的并发修改

时间:2016-11-29 14:34:09

标签: java multithreading jdbc proxool

我正在尝试使用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;
}

当我启动我的服务器时,会发生的情况是,超过1个线程尝试并行访问此代码并引发并发修改异常。

据我所知,可以通过为synchronized块提供类级锁来修复它。但它会严重影响性能。

对此更好的解决方案?

1 个答案:

答案 0 :(得分:1)

对我而言,您的问题与info更相关,Properties显然是共享Properties的实例。知道Hashtable扩展HashtableConcurrentModificationException会抛出Hashtable,如果您按照javadoc中所述的方式更改其结构:

  

如果ConcurrentModificationException在结构修改后的任何时间   迭代器以任何方式创建,除非通过迭代器自己创建   删除方法,迭代器会抛出一个   Hashtable

如果您有多个线程并行调用此方法,他们可以同时删除修改DriverManager.getConnection(connectionPoolUrl, info)结构的属性,并在ConcurrentModificationException内迭代它,最终会得到{{1} }}

您应该做的是将info转换为线程安全的ConcurrentHashMap<Object, Object>,并允许同时修改和迭代。然后,您将DriverManager.getConnection的{​​{1}}实例作为参数提供给Properties作为下一个:

info