Hibernate用ThreadLocal模式(线程局部变量模式)管理Session

 更新时间:2019年03月29日 15:45:05   作者:徐刘根  
今天小编就为大家分享一篇关于Hibernate用ThreadLocal模式(线程局部变量模式)管理Session,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

Hibernate ThreadLocal

它会为每个线程维护一个私有的变量空间。实际上, 其实现原理是在JVM 中维护一个Map,这个Map的key 就是当前的线程对象,而value则是 线程通过Hibernate ThreadLocal.set方法保存的对象实例。当线程调用Hibernate ThreadLocal.get方法时, Hibernate ThreadLocal会根据当前线程对象的引用,取出Map中对应的对象返回。

这样,Hibernate ThreadLocal通过以各个线程对象的引用作为区分,从而将不同线程的变量隔离开来。

一、ThreadLocal模式 (线程局部变量模式) 管理Session的理解

(1)在利用Hibernate开发的时候如何合理的管理Session,避免Session的频繁创建和销毁,对于提高系统的性能来说是非常重要的!

(2)我们知道Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例,但是遗憾的是Session不是线程安全的。

(3)Session中包含了数据库操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD(数据库的增删改查),就很有可能导致数据存取的混乱,我们根本无法想像那些你根本不能预测执行顺序的线程对你的一条记录进行操作的情形!

(4)在Session的众多管理方案中,在今天的学习中知道ThreadLocal模式是一种很不错的解决方案,特分享给大家!

(5)我们首先要明白的是ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。(也许把它命名为ThreadLocalVar更加合适)。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用某变量的线程都提供一个该变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有一个该变量。

(6)更具体的来说就是:ThreadLocal并非等同于线程成员变量,ThreadLocal该类提供了线程局部变量。这个局部变量与一般的成员变量不一样,ThreadLocal的变量在被多个线程使用时候,每个线程只能拿到该变量的一个副本,这是Java API中的描述,但更准确的说,应该是ThreadLocal类型的变量内部的注册表(Map<Thread,T>)发生了变化,但ThreadLocal类型的变量本身的确是一个,这才是本质!

(7)ThreadLocal的原理:在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。比如下面的示例实现:

public class ThreadLocal {
<span style="white-space:pre"> </span>private Map values = Collections.synchronizedMap(new HashMap());
<span style="white-space:pre"> </span>public Object get() {
<span style="white-space:pre"> </span>Thread curThread = Thread.currentThread();
<span style="white-space:pre"> </span>Object o = values.get(curThread);
<span style="white-space:pre"> </span>if (o == null && !values.containsKey(curThread)) {
<span style="white-space:pre">  </span>o = initialValue();
<span style="white-space:pre">  </span>values.put(curThread, o);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>values.put(Thread.currentThread(), newValue);
<span style="white-space:pre"> </span>return o;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public Object initialValue() {
<span style="white-space:pre"> </span>return null;
<span style="white-space:pre"> </span>}
}

二、代码的展示

(1)使用ThreadLocal模式 (线程局部变量模式) 管理Session的代码如下:

<span style="font-family:System;font-size:14px;">package com.lc.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
 * 升级的MySessionFactory 线程局部模式
 * @author xuliugen
 */
public class HibernateUtil {
 private static SessionFactory sessionFactory = null;
 // 使用线程局部模式
 private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
 /*
 * 默认的构造函数
 */
 private HibernateUtil() {
 }
 /*
 * 静态的代码块
 */
 static {
 sessionFactory = new Configuration().configure().buildSessionFactory();
 }
 /*
 * 获取全新的的session
 */
 public static Session openSession() {
 return sessionFactory.openSession();
 }
 /*
 * 获取和线程关联的session
 */
 public static Session getCurrentSession() {
 Session session = threadLocal.get();
 // 判断是是是否得到
 if (session == null) {
  session = sessionFactory.openSession();
  // 把session放到 threadLocal,相当于该session已经于线程绑定
  threadLocal.set(session);
 }
 return session;
 }
}</span>

(2)测试代码如下:

<span style="font-family:System;font-size:14px;">package com.lc.view;
import org.hibernate.Session;
import com.lc.util.HibernateUtil;
public class TestHibernateUtil {
 public static void main(String[] args) {
 Session s1 = HibernateUtil.getCurrentSession(); 
 Session s2 = HibernateUtil.getCurrentSession();
 System.out.println(s1.hashCode()+"  "+s2.hashCode());
 /*
  * 1432950766  1432950766
  * 结果是两个hashCode是一样的,证明是线程相关的
  */
 }
}</span><span style="font-family:System;font-size:14px;">
</span>

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • java中的Io(input与output)操作总结(四)

    java中的Io(input与output)操作总结(四)

    前面已经把java io的主要操作讲完了,这一节我们来说说关于java io的其他内容:Serializable序列化/DataOutputStream和DataInputStream类/管道流等等,感兴趣的朋友可以了解下
    2013-01-01
  • Java 添加、替换、删除PDF中的图片的示例代码

    Java 添加、替换、删除PDF中的图片的示例代码

    这篇文章主要介绍了Java 添加、替换、删除PDF中的图片,本文通过示例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • 基于Feign传输对象无法接收参数的问题

    基于Feign传输对象无法接收参数的问题

    这篇文章主要介绍了基于Feign传输对象无法接收参数的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 基于Session的国际化实现方法

    基于Session的国际化实现方法

    下面小编就为大家带来一篇基于Session的国际化实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • mybatis深入讲解resultMap的定义及用法

    mybatis深入讲解resultMap的定义及用法

    MyBatis的每一个查询映射的返回类型都是ResultMap,当我们提供返回类型属性是resultType时,MyBatis会自动给我们把对应值赋给resultType所指定对象的属性,当我们提供返回类型是resultMap时,将数据库中列数据复制到对象的相应属性上,可以用于复制查询,两者不能同时用
    2022-04-04
  • Java enum关键字不识别的快速解决办法

    Java enum关键字不识别的快速解决办法

    这篇文章主要介绍了Java enum关键字不识别的快速解决办法,非常不错,具有参考借鉴价值,感兴趣的朋友一起看看吧
    2016-09-09
  • Java流程控制之顺序结构

    Java流程控制之顺序结构

    Java中的流程控制语句可以这样分类:顺序结构,选择结构,循环结构。下面文章我们就来看看来顺序结构的详细介绍,主要以顺序结构简单图示及详细解说该内容,需要的小伙伴可以参考一下
    2021-12-12
  • jvm排查工具箱jvm-tools下载使用详解

    jvm排查工具箱jvm-tools下载使用详解

    这篇文章主要为大家介绍了jvm排查工具箱jvm-tools下载使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 没有编辑器的环境下是如何创建Servlet(Tomcat+Java)项目的?

    没有编辑器的环境下是如何创建Servlet(Tomcat+Java)项目的?

    今天给大家带来的是关于Java的相关知识,文章围绕着在没有编辑器的环境下如何创建Servlet(Tomcat+Java)项目展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • Java实现三子棋小游戏简易版

    Java实现三子棋小游戏简易版

    这篇文章主要为大家详细介绍了Java实现三子棋小游戏简易版,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05

最新评论