Hibernate用ThreadLocal模式(线程局部变量模式)管理Session
作者:徐刘根 发布时间:2021-10-01 18:50:10
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>
来源:https://blog.csdn.net/xlgen157387/article/details/39780419


猜你喜欢
- 批注是一种富文本注释,常用于为指定的Excel单元格添加提示或附加信息。 Free Spire.XLS for Java为开发人员免费提供了
- 是不是很讨厌mybatis Generator帮我们生成代码的时候在Mapper和mapper.xml文件中生成的一大堆注解?今天在看MyB
- 在开发中当程序发生ANR或者异常,我们会将信息存在本地,然后上传服务器,这样可以实时去发现问题修改问题。那我们需要获取文件之后需要对文件进行
- 简介使用配置类和注解代替web.xml和SpringMVC配置文件的功能在Servlet3.0环境中,容器会在类路径中查找实现javax.s
- 本文实例为大家分享了SSM实现学生管理系统的具体代码,供大家参考,具体内容如下概述基于Spring + Spring MVC 的学生管理系统
- Struts2是Struts社区和WebWork社区的共同成果,我们甚至可以说,Struts2是WebWork的升级版,他采用的正是WebW
- package com.ysh.file;import java.util.ArrayList;import java.util.Linke
- Java 8 , Lambda + foreach 语法糖, 写起来非常的 cleanpublic static void main(Str
- 折半插入排序折半插入排序是对直接插入排序的简单改进。此处介绍的折半插入,其实就是通过不断地折半来快速确定第i个元素的插入位置,这实际上是一种
- Understanding AsyncTaskAsyncTask是Android 1.5 Cubake加入的用于实现异步操作的一个类,在此之
- JAVA中Integer类下的常用方法有哪些?1.进制转换 n进制转10进制 字符串结果Integer.parseInt(String s,
- 引言在Flutter开发中,所有的组件和页面都继承自Widget,所以探索页面的生命周期其实就是Widget的生命周期。 在 Flutter
- 实例如下:import java.lang.reflect.Field;import java.lang.reflect.Invocatio
- 1 原码、反码、补码原码:将十进制转化为二进制即原码;反码:正数的反码与原码相同,负数的反码(除却最高位的符号位不变)与原码相反
- 插件安装方式:新版本IDE安装方式略有不同,不一一赘述 1、Background Image Plus
- 主要思想:将一个view设计成多层:背景层,含中奖信息等;遮盖层,用于刮奖,使用关联一个Bitmap的Canvas在该Bitmap上,使用它
- 有时候,我们使用AOP来进行放的增强,编写切面类的时候,需要定位在哪个方法上试用该切面进行增强,本片文章主要讲解两种在SpringBoot中
- 在《Android Handler之消息循环的深入解析》中谈到了Handler是用于操作线程内部的消息队列,所以Handler可以用来线程间
- Android的闹钟实现机制, 需要调用AlarmManager.set()将闹铃时间记录到系统中,当闹铃时间到后,系统会给应用程序发送广播
- 一. 析构方法1. 概念我们现在已经知道,构造方法负责创建一个Java的类对象,并可以对该对象进行初始化。与此相对应的,其实还有一个方法,可