<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    沉睡森林@漂在北京

    本處文章除注明“轉載”外均為原創,轉載請注明出處。

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      152 隨筆 :: 4 文章 :: 114 評論 :: 0 Trackbacks
    下面的代碼是我在研究數據庫連接池化和事物控制時寫的,看似沒有什么問題的代碼,其實隱藏了一個十分嚴重的問題。
    1.
    package com.example.ds;

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.List;

    //import java.util.concurrent.ConcurrentHashMap;

    public class ConnectFactory {

        
    private HashMap<String, UserConn> userConnPools;
        
    private static int MAX_CONN_NUM = 15;
        
    public ArrayList<Connection> idleConnPools;

        
    private ConnectFactory() {
            userConnPools 
    = new HashMap<String, UserConn>();
            idleConnPools 
    = new ArrayList<Connection>();

            
    try {
                Class.forName(
    "org.gjt.mm.mysql.Driver").newInstance();
            } 
    catch (Exception e) {
                e.printStackTrace();
                System.out.println(
    "==>注冊驅動程序錯誤!");
            }
            
    for (int i = 0; i < MAX_CONN_NUM; i++) {
                
    try {
                    Connection conn 
    = DriverManager.getConnection("jdbc:mysql://localhost/jpetstore?user=mysql_user&password=sa&useunicode=true&characterencoding=utf8");
                    idleConnPools.add(conn);
                } 
    catch (SQLException e) {
                    e.printStackTrace();
                    System.out.println(
    "==>初始化idleConnPools錯誤!");
                }
            }
            System.out.println(
    "==>注冊Connection成功!");
        }

        
    // private ConnPools connPools;
        private static final ConnectFactory _instance = new ConnectFactory();

        
    public static ConnectFactory getInstance() {
            
    return _instance;
        }

        
    public Connection getConn() {
            String threadId 
    = com.example.thread.ThreadValue.getThreadId();
            System.out.println(
    "==>獲取線程號:" + threadId);
            UserConn userConn 
    = null;
            
    try {
                userConn 
    = userConnPools.get(threadId);
            } 
    catch (Exception e) {
                
    // TODO: handle exception
                System.out.println("==>獲取UserConn錯誤!");
            }

            
    if (userConn == null) {
                
    if (idleConnPools.size() > 0) {
                    Connection conn 
    = idleConnPools.remove(idleConnPools.size() - 1);
                    userConn 
    = new UserConn(conn);
                    userConnPools.put(threadId, userConn);
                } 
    else {
                    
    throw new RuntimeException("所有可以使用的連接均在使用中!");
                }
            }
            System.out.println(
    "分配Conn成功,線程號:" + threadId);
            
    return userConn.getConn();
        }

        
    public void closeConn() {
            String threadId 
    = com.example.thread.ThreadValue.getThreadId();
            UserConn userConn 
    = userConnPools.remove(threadId);
            
    if (userConn != null) {
                Connection conn 
    = userConn.getConn();
                idleConnPools.add(conn);
                userConn.closeConn();
            } 
    else {
                
    throw new RuntimeException("返回不需要使用的連接時錯誤!");
            }
        }

        
    public List getIdelConnPools() {
            
    return idleConnPools;
        }

        
    public Collection<UserConn> getUserConnPools() {
            
    return userConnPools.values();
        }

    }


    2.
    package com.example.ds;

    import java.sql.Connection;

    public class UserConn {

        
    private static int count_num = 0;
        
    private Connection conn;
        
    private int flowId = 0;
        
    private boolean beUsed;
        
    private String threadId;

        
    public boolean isBeUsed() {
            
    return beUsed;
        }

        
    public String getThreadId() {
            
    return threadId;
        }

        
    public UserConn(Connection conn1) {
            flowId 
    = count_num++;
            beUsed 
    = false;
            conn 
    = conn1;
        }

        
    public Connection getConn() {
            beUsed 
    = true;
            
    return conn;
        }

        
    public void closeConn() {
            beUsed 
    = false;
        }

        
    public String toString() {
            
    return (new StringBuffer()).append("==>UserConn=[flowId=").append(flowId).append(",beUsed=").append(beUsed).append("]").toString();
        }

    }


    當多個線程同時訪問ConnectFactory時,ConnectFactory的getConn和closeConn方法在處理ArrayList和HashMap時就面臨著同步的問題。即兩個線程同時獲取到了一個idle的Conn,而userConnPools里面就會有一個重復的Conn,導致事物上面處理的混亂。


    posted on 2009-03-07 16:08 王總兵 閱讀(192) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲码在线中文在线观看| 亚洲av无码国产精品色午夜字幕 | 久久99免费视频| 国产亚洲美女精品久久久| 国产精品高清免费网站 | 成人性生活免费视频| 亚洲av极品无码专区在线观看 | 免费无码一区二区三区蜜桃大| 亚洲人成网站免费播放| 在线a人片天堂免费观看高清| 狠狠入ady亚洲精品| 亚洲人成网站在线观看青青| 人与动性xxxxx免费| 亚洲精品少妇30p| 热re99久久6国产精品免费| 亚洲免费观看在线视频| 成人毛片手机版免费看| 理论秋霞在线看免费| 国产精一品亚洲二区在线播放| 1a级毛片免费观看| 亚洲AV无码一区二区三区性色 | 亚洲精品免费在线| 亚洲精品无码av片| 久久久久亚洲精品无码网址| 亚洲免费精彩视频在线观看| 亚洲综合校园春色| 亚洲国产成人久久一区久久| 日韩精品免费视频| 亚洲砖码砖专无区2023 | 免费人成网站在线观看10分钟| 亚洲依依成人亚洲社区| 亚洲综合av永久无码精品一区二区| 久久国产精品免费网站| 亚洲国产综合AV在线观看| 亚洲精品中文字幕乱码三区| 免费看成人AA片无码视频羞羞网| 国产精品亚洲一区二区三区在线观看 | 国产精品日本亚洲777| 亚洲国产精品久久| 又粗又大又猛又爽免费视频| 99爱视频99爱在线观看免费|