您的位置:首页 > 数据库

ConcurrentHashMap实现数据库连接的线程安全问题

2018-01-15 12:41 525 查看
private ConcurrentHashMap<String,FutureTask<Connection>>connectionPool = newConcurrentHashMap<String, FutureTask<Connection>>();

public Connection getConnection(String key) throws Exception{
FutureTask<Connection>connectionTask=connectionPool.get(key);
if(connectionTask!=null){
return connectionTask.get();
}
else{
Callable<Connection> callable = new Callable<Connection>(){
@Override
public Connection call() throws Exception {
// TODO Auto-generated method stub
return createConnection();
}
};
FutureTask<Connection>newTask = new FutureTask<Connection>(callable);
connectionTask = connectionPool.putIfAbsent(key, newTask);
if(connectionTask==null){
connectionTask = newTask;
connectionTask.run();
}
return connectionTask.get();
}
}

//创建Connection
private Connection createConnection(){
return null;
}

这是在网上看到的一段 ConcurrentHashMap实现数据库连接的代码,发现有个问题:
就是在线程A、B同时执行获取数据库连接的方法时,如果线程A执行完17行,返回null,说明它是首个存入该key的线程,但是不幸的是A线程因为某些原因此时突然挂掉了。线程B执行到17行时发现此时已经有线程存入了key,connectionTask不为null,则直接跳到22行去get数据库连接,但是因为线程A没有执行完创建连接,所以线程B就一直阻塞在get方法上。请各位大神看看是不是存在这个问题,如果存在,如何更好的解决?

问题解决:在可能出现异常的地方添加一个异常捕获,如果发生异常就将之前添加的key-value删除,我理解这样就可避免线程无限阻塞的问题了,各位看看还有没有其他问题,欢迎留言

try {
if (connectionFutureTask==null) {
connectionFutureTask = newTask;
connectionFutureTask.run();
}
} catch (Exception e) {
connectionPool.remove(key, newTask);
e.printStackTrace();
throw new RuntimeException("connectionCreateFail!!!");
}
return connectionFutureTask.get();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多线程 同步
相关文章推荐