您好,登錄后才能下訂單哦!
好程序員Java學(xué)習(xí)路線分享MyBatis之線程優(yōu)化,我們的項目存在大量用戶同時訪問的情況,那么就會出現(xiàn)大量線程并發(fā)訪問數(shù)據(jù)庫,這樣會帶來線程同步問題,本章我們將討論MyBatis的線程同步問題和優(yōu)化方法。
?
MyBatis需要通過SqlSession實現(xiàn)數(shù)據(jù)庫操作,而SQLSession內(nèi)部的實現(xiàn)需要使用JDBC的Connection連接對象,而Connection對象是非線程安全的,當(dāng)多個線程同時
訪問時,就可能出現(xiàn)線程同步的問題。
我們前面學(xué)習(xí)過解決線程同步的方法是:鎖機制
我們可以給所有數(shù)據(jù)庫相關(guān)方法或代碼添加synchronized關(guān)鍵字,本質(zhì)上是讓所有線程排隊執(zhí)行這些操作。
這樣解決了線程同步問題,但是會帶來執(zhí)行效率的降低,如果大量的用戶訪問時會導(dǎo)致長時間的等待,所以今天我們將學(xué)習(xí)另一種解決方法。
ThreadLocal(線程局部變量),可以為每個線程創(chuàng)建對象的副本,這樣就不存在多線程訪問一個對象的情況,以空間換時間,效率高,速度快,但是內(nèi)存空間消耗更大。
創(chuàng)建方法:
ThreadLocal<數(shù)據(jù)的類型> threadLocal = new ThreadLocal<數(shù)據(jù)類型>();
數(shù)據(jù)的類型是每個線程中需要保存數(shù)據(jù)的類型
數(shù)據(jù)存?。?/p>
void set(Object?數(shù)據(jù))?將數(shù)據(jù)和當(dāng)前線程綁定起來
Object get()?從當(dāng)前線程中獲得綁定的數(shù)據(jù)
?
Session線程安全的優(yōu)化方法
1)創(chuàng)建ThreadLocal來保存SqlSession
2)編寫獲得SqlSession的方法
1)調(diào)用ThreadLocal的get方法來獲得SqlSession
2)如果SqlSession對象為null,調(diào)用工廠來創(chuàng)建SqlSession,使用ThreadLocal的set方法保存到線程中,返回SqlSession對象
3)如果SqlSession對象不為null,就直接返回
示例代碼:
/**
?* MyBatis工具類
?*?用于獲得當(dāng)前線程中的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;
????/**
?????*?創(chuàng)建工廠
?????*/
????public static void buildFactory(){
????????try {
????????????factory = new SqlSessionFactoryBuilder().build(
????????????????????Resources.getResourceAsStream(CONFIG_FILENAME));
????????} catch (IOException e) {
????????????e.printStackTrace();
????????}
????}
????//在靜態(tài)代碼塊中執(zhí)行,保證工廠的創(chuàng)建只執(zhí)行一次
????static{
????????buildFactory();
????}
????/**
?????*?從當(dāng)前線程中獲得Session
?????* @return
?????*/
????public static SqlSession getSession(){
????????//從ThreadLocal獲得線程中的SqlSession
????????SqlSession sqlSession = threadLocal.get();
????????if(sqlSession == null){
????????????//如果SqlSession為空,創(chuàng)建SqlSession
????????????if(factory == null){
????????????????buildFactory();
????????????}
????????????sqlSession = factory.openSession();
????????????//把新創(chuàng)建的SqlSession,存入到ThreadLocal,綁定到線程中
????????????threadLocal.set(sqlSession);
????????}
????????return sqlSession;
????}
????/**
?????*?關(guān)閉Session
?????*/
????public static void closeSession(){
????????//從ThreadLocal獲得線程中的SqlSession
????????SqlSession sqlSession = threadLocal.get();
????????if(sqlSession != null){
????????????//關(guān)閉會話
????????????sqlSession.close();
????????????//設(shè)置為null,gc會盡快回收
????????????sqlSession = null;
????????????//刪除掉ThreadLocal中的SqlSession
????????????threadLocal.set(null);
????????}
????}
}
?
總結(jié)
線程同步是進(jìn)行JavaEE開發(fā)需要重點考慮的問題,MyBatis的SQLSession有線程同步問題,使用ThreadLocal為每個線程綁定自己的SQLSession副本,可以解決線程同步問題,同時不會降低程序執(zhí)行效率。
?
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。