- 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();