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;
}

一旦我启动服务器,就会发生超过 1 个线程尝试并行访问此代码并引发并发修改异常。

我知道可以通过为同步块提供类级锁定来修复它。但是会严重影响性能。

有什么更好的解决方案吗?

4

1 回答 1

1

info对我来说,您的问题与哪个显然Properties是共享的实例更相关。知道PropertiesextendsHashtable和 an Hashtable将抛出 a ConcurrentModificationException如果您在迭代时更改其结构,如 javadoc 中所述:

如果在Hashtable创建迭代器后的任何时候对 进行结构修改,除了通过迭代器自己的 remove 方法之外的任何方式,迭代器都会抛出一个 ConcurrentModificationException.

在这里,如果您有多个线程并行调用此方法,它们可以同时删除修改您的结构的属性Hashtable并对其进行迭代,DriverManager.getConnection(connectionPoolUrl, info)最终会得到一个ConcurrentModificationException.

您应该做的是转换infoConcurrentHashMap<Object, Object>线程安全的并允许同时修改和迭代的。然后,您将提供作为参数DriverManager.getConnectionProperties从下一个创建的实例info

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 回答