ITPub博客

首页 > 应用开发 > Java > 好程序员Java学习路线分享MyBatis之线程优化

好程序员Java学习路线分享MyBatis之线程优化

原创 Java 作者:好程序员IT 时间:2019-09-19 11:43:14 0 删除 编辑

  好程序员Java 学习路线分享 MyBatis 之线程优化,我们的项目存在大量用户同时访问的情况,那么就会出现大量线程并发访问数据库,这样会带来线程同步问题,本章我们将讨论 MyBatis 的线程同步问题和优化方法。

 

MyBatis 的线程同步问题

MyBatis 需要通过 SqlSession 实现数据库操作,而 SQLSession 内部的实现需要使用 JDBC 的 Connection 连接对象,而 Connection 对象是非线程安全的,当多个线程同时

访问时,就可能出现线程同步的问题。

线程同步的解决方法

我们前面学习过解决线程同步的方法是:锁机制

我们可以给所有数据库相关方法或代码添加synchronized 关键字,本质上是让所有线程排队执行这些操作。


这样解决了线程同步问题,但是会带来执行效率的降低,如果大量的用户访问时会导致长时间的等待,所以今天我们将学习另一种解决方法。

ThreadLocal 解决线程同步

ThreadLocal (线程局部变量),可以为每个线程创建对象的副本,这样就不存在多线程访问一个对象的情况,以空间换时间,效率高,速度快,但是内存空间消耗更大。


ThreadLocal 的用法

创建方法:

ThreadLocal< 数据的类型 > threadLocal = new ThreadLocal< 数据类型 >();

数据的类型是每个线程中需要保存数据的类型

数据存取:

void set(Object  数据 )  将数据和当前线程绑定起来

Object get()  从当前线程中获得绑定的数据

 

Session 线程安全的优化方法

1 )创建 ThreadLocal 来保存 SqlSession

2 )编写获得 SqlSession 的方法

1 )调用 ThreadLocal 的 get 方法来获得 SqlSession

2 )如果 SqlSession 对象为 null ,调用工厂来创建 SqlSession ,使用 ThreadLocal 的 set 方法保存到线程中,返回 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();

            // 设置为 null , gc 会尽快回收

            sqlSession = null;

            // 删除掉 ThreadLocal 中的 SqlSession

            threadLocal.set(null);

        }

    }

}

 

总结

线程同步是进行JavaEE 开发需要重点考虑的问题, MyBatis 的 SQLSession 有线程同步问题,使用 ThreadLocal 为每个线程绑定自己的 SQLSession 副本,可以解决线程同步问题,同时不会降低程序执行效率。

 


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69913892/viewspace-2657526/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
欢迎关注公众号:好程序员特训营 web前端教程分享 723729549 大数据教程分享 703503210

注册时间:2019-03-20

  • 博文量
    539
  • 访问量
    410787