2016-11-29 49 views
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個多線程試圖訪問平行此代碼,它拋出併發修改例外。

我知道它可以通過提供級別鎖定到同步塊來解決。但這會嚴重影響性能。

任何更好的解決方案呢?

+0

請你加堆棧跟蹤? –

+1

也顯示你如何定義'info' –

回答

1

對我而言,您的問題更多地與info相關,這顯然是共享的Properties的實例。明知Properties延伸HashtableHashtable將拋出一個ConcurrentModificationException如果你改變它的結構,同時遍歷它說成的Javadoc:

如果Hashtable是在 迭代器被創建,在之後的任何時間結構修飾除了通過迭代器自己的 刪除方法之外的任何方式,迭代器都會拋出 ConcurrentModificationException

在這裏,如果你有多個線程調用並行這種方法,他們可以同時內DriverManager.getConnection(connectionPoolUrl, info)刪除哪些修改您的Hashtable的結構特性和遍歷它這將結束與一個ConcurrentModificationException

你應該做的是將info轉換爲ConcurrentHashMap<Object, Object>這是線程安全的,並允許同時修改和迭代。然後,你將提供作爲參數傳遞給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); 
+1

這確實是個問題。我嘗試了你所建議的修復方法,它工作正常!非常感謝 ! – user2730428