我试图在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个线程尝试并行地访问这段代码,并引发并发修改异常。
我理解可以通过为同步块提供类级锁来修复它。但这会严重影响演出。
有什么更好的解决办法吗?
发布于 2016-11-29 14:59:24
对我来说,您的问题更多地与info有关,它显然是共享的Properties的一个实例。知道Properties扩展了Hashtable,如果在迭代结构的同时改变结构,Hashtable就会抛出一个ConcurrentModificationException,就像javadoc中所说的那样:
如果在创建迭代器之后的任何时候对
Hashtable进行了结构修改,那么除了通过迭代器自己的remove方法之外,迭代器将以任何方式抛出一个ConcurrentModificationException。
在这里,如果有几个线程并行地调用这个方法,它们可以并发地删除修改Hashtable结构的属性,并在DriverManager.getConnection(connectionPoolUrl, info)中迭代它,这最终会得到一个ConcurrentModificationException。
您应该做的是将info转换为线程安全的ConcurrentHashMap,并允许并发修改和迭代。然后将作为参数提供给DriverManager.getConnection,这是一个从info创建的Properties实例,如下所示:
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);https://stackoverflow.com/questions/40868485
复制相似问题