请选择 进入手机版 | 继续访问电脑版

好程序员-千锋教育旗下高端IT职业教育品牌

400-811-9990
我的账户
好程序员

专注高端IT职业培训

亲爱的猿猿,欢迎!

已有账号,请

如尚未注册?

[JavaEE] 好程序员Java培训学习路线分享MyBatis之线程优化

[复制链接]
叶子老师 发表于 2019-9-18 17:45:07 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
  好程序员Java培训学习路线分享MyBatis之线程优化,我们的项目存在大量用户同时访问的情况,那么就会出现大量线程并发访问数据库,这样会带来线程同步问题,本章我们将讨论MyBatis的线程同步问题和优化方法。
MyBatis的线程同步问题
MyBatis需要通过SqlSession实现数据库操作,而SQLSession内部的实现需要使用JDBCConnection连接对象,而Connection对象是非线程安全的,当多个线程同时
访问时,就可能出现线程同步的问题。
线程同步的解决方法
我们前面学习过解决线程同步的方法是:锁机制
我们可以给所有数据库相关方法或代码添加synchronized关键字,本质上是让所有线程排队执行这些操作。
图片6.png
这样解决了线程同步问题,但是会带来执行效率的降低,如果大量的用户访问时会导致长时间的等待,所以今天我们将学习另一种解决方法。
ThreadLocal解决线程同步
ThreadLocal(线程局部变量),可以为每个线程创建对象的副本,这样就不存在多线程访问一个对象的情况,以空间换时间,效率高,速度快,但是内存空间消耗更大。
图片7.png
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副本,可以解决线程同步问题,同时不会降低程序执行效率。
好程序员Java培训官网:http://www.goodprogrammer.org/

精彩内容,一键分享给更多人!
回复

使用道具 举报

您需要登录后才可以回帖

本版积分规则

关注我们
好程序员
千锋好程序员

北京校区(总部):北京市海淀区宝盛北里西区28号中关村智诚科创大厦

深圳西部硅谷校区:深圳市宝安区宝安大道5010号深圳西部硅谷B座A区605-619

杭州龙驰智慧谷校区:浙江省杭州市下沙经济技术开发区元成路199号龙驰智慧谷B座7层

郑州校区:郑州市二七区航海中路60号海为科技园C区10层、12层

Copyright 2007-2019 北京千锋互联科技有限公司 .All Right

京ICP备12003911号-5 京公安网11010802011455号

请您保持通讯畅通1对1咨询马上开启