全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术干货

MyBatis之线程优化

发布时间:2019-09-18 15:57:00
发布人:小锋

  前言

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

  MyBatis的线程同步问题

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

  线程同步的解决方法

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

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

图片1

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

  ThreadLocal解决线程同步

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

图片2

  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 threadLocal = new ThreadLocal();

  //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副本,可以解决线程同步问题,同时不会降低程序执行效率。

相关文章

普通的程序员和大神级的程序员有什么区别?

普通的程序员和大神级的程序员有什么区别?

2023-10-14
Intel CPU 后面的K、KF、F有什么区别?

Intel CPU 后面的K、KF、F有什么区别?

2023-10-14
C语言中的i ++和i = i + 1有什么区别?

C语言中的i ++和i = i + 1有什么区别?

2023-10-14
8位有符号数的取值范围下限为什么是-128?

8位有符号数的取值范围下限为什么是-128?

2023-10-14

最新文章

常见网络安全面试题:Windows常用的命令有哪些?

常见网络安全面试题:Windows常用的命令有哪些?

2023-10-09
常见网络安全面试题:根据设备告警如何展开排查?

常见网络安全面试题:根据设备告警如何展开排查?

2023-10-09
常见网络安全面试题:mysql加固呢?(数据库加固)

常见网络安全面试题:mysql加固呢?(数据库加固)

2023-10-09
常见网络安全面试题:windows和linux加固?(操作系统加固)

常见网络安全面试题:windows和linux加固?(操作系统加固)

2023-10-09
在线咨询 免费试学 教程领取