好程序員Java學習路線分享MyBatis之線程優化

  好程序員Java學習路線分享MyBatis之線程優化,我們的項目存在大量用戶同時訪問的情況,那麼就會出現大量線程併發訪問數據庫,這樣會帶來線程同步問題,本章我們將討論MyBatis的線程同步問題和優化方法。

 

MyBatis的線程同步問題

MyBatis需要通過SqlSession實現數據庫操作,而SQLSession內部的實現需要使用JDBCConnection連接對象,而Connection對象是非線程安全的,當多個線程同時

訪問時,就可能出現線程同步的問題。

線程同步的解決方法

我們前面學習過解決線程同步的方法是:鎖機制

我們可以給所有數據庫相關方法或代碼添加synchronized關鍵字,本質上是讓所有線程排隊執行這些操作。


這樣解決了線程同步問題,但是會帶來執行效率的降低,如果大量的用戶訪問時會導致長時間的等待,所以今天我們將學習另一種解決方法。

ThreadLocal解決線程同步

ThreadLocal(線程局部變量),可以爲每個線程創建對象的副本,這樣就不存在多線程訪問一個對象的情況,以空間換時間,效率高,速度快,但是內存空間消耗更大。


ThreadLocal的用法

創建方法:

ThreadLocal<數據的類型> threadLocal = new ThreadLocal<數據類型>();

數據的類型是每個線程中需要保存數據的類型

數據存取:

void set(Object 數據將數據和當前線程綁定起來

Object get() 從當前線程中獲得綁定的數據

 

Session線程安全的優化方法

1)創建ThreadLocal來保存SqlSession

2)編寫獲得SqlSession的方法

1)調用ThreadLocalget方法來獲得SqlSession

2)如果SqlSession對象爲null,調用工廠來創建SqlSession,使用ThreadLocalset方法保存到線程中,返回SqlSession對象

3)如果SqlSession對象不爲null,就直接返回

示例代碼:

/**

 * MyBatis工具類

 * 用於獲得當前線程中的SqlSession

 * 使用ThreadLocal解決線程安全問題

 */

public class MyBatisUtils {

 

    public static final String CONFIG_FILENAME = "mybatis-config.xml";

    //使用ThreadLocal保存SQLSession對象

    private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();

    //SqlSession的工廠,單例

    private static SqlSessionFactory factory = null;

    /**

     * 創建工廠

     */

    public static void buildFactory(){

        try {

            factory = new SqlSessionFactoryBuilder().build(

                    Resources.getResourceAsStream(CONFIG_FILENAME));

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    //在靜態代碼塊中執行,保證工廠的創建只執行一次

    static{

        buildFactory();

    }

    /**

     * 從當前線程中獲得Session

     * @return

     */

    public static SqlSession getSession(){

        //ThreadLocal獲得線程中的SqlSession

        SqlSession sqlSession = threadLocal.get();

        if(sqlSession == null){

            //如果SqlSession爲空,創建SqlSession

            if(factory == null){

                buildFactory();

            }

            sqlSession = factory.openSession();

            //把新創建的SqlSession,存入到ThreadLocal,綁定到線程中

            threadLocal.set(sqlSession);

        }

        return sqlSession;

    }

    /**

     * 關閉Session

     */

    public static void closeSession(){

        //ThreadLocal獲得線程中的SqlSession

        SqlSession sqlSession = threadLocal.get();

        if(sqlSession != null){

            //關閉會話

            sqlSession.close();

            //設置爲nullgc會盡快回收

            sqlSession = null;

            //刪除掉ThreadLocal中的SqlSession

            threadLocal.set(null);

        }

    }

}

 

總結

線程同步是進行JavaEE開發需要重點考慮的問題,MyBatisSQLSession有線程同步問題,使用ThreadLocal爲每個線程綁定自己的SQLSession副本,可以解決線程同步問題,同時不會降低程序執行效率。

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章