Hibernate用ThreadLocal模式(線程局部變量模式)管理Session
Hibernate ThreadLocal
它會為每個線程維護一個私有的變量空間。實際上, 其實現(xiàn)原理是在JVM 中維護一個Map,這個Map的key 就是當前的線程對象,而value則是 線程通過Hibernate ThreadLocal.set方法保存的對象實例。當線程調(diào)用Hibernate ThreadLocal.get方法時, Hibernate ThreadLocal會根據(jù)當前線程對象的引用,取出Map中對應的對象返回。
這樣,Hibernate ThreadLocal通過以各個線程對象的引用作為區(qū)分,從而將不同線程的變量隔離開來。
一、ThreadLocal模式 (線程局部變量模式) 管理Session的理解
(1)在利用Hibernate開發(fā)的時候如何合理的管理Session,避免Session的頻繁創(chuàng)建和銷毀,對于提高系統(tǒng)的性能來說是非常重要的!
(2)我們知道Session是由SessionFactory負責創(chuàng)建的,而SessionFactory的實現(xiàn)是線程安全的,多個并發(fā)的線程可以同時訪問一個SessionFactory并從中獲取Session實例,但是遺憾的是Session不是線程安全的。
(3)Session中包含了數(shù)據(jù)庫操作相關的狀態(tài)信息,那么說如果多個線程同時使用一個Session實例進行CRUD(數(shù)據(jù)庫的增刪改查),就很有可能導致數(shù)據(jù)存取的混亂,我們根本無法想像那些你根本不能預測執(zhí)行順序的線程對你的一條記錄進行操作的情形!
(4)在Session的眾多管理方案中,在今天的學習中知道ThreadLocal模式是一種很不錯的解決方案,特分享給大家!
(5)我們首先要明白的是ThreadLocal并非是一個線程的本地實現(xiàn)版本,它并不是一個Thread,而是thread local variable(線程局部變量)。(也許把它命名為ThreadLocalVar更加合適)。線程局部變量(ThreadLocal)其實的功用非常簡單,就是為每一個使用某變量的線程都提供一個該變量值的副本,是每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本沖突。從線程的角度看,就好像每一個線程都完全擁有一個該變量。
(6)更具體的來說就是:ThreadLocal并非等同于線程成員變量,ThreadLocal該類提供了線程局部變量。這個局部變量與一般的成員變量不一樣,ThreadLocal的變量在被多個線程使用時候,每個線程只能拿到該變量的一個副本,這是Java API中的描述,但更準確的說,應該是ThreadLocal類型的變量內(nèi)部的注冊表(Map<Thread,T>)發(fā)生了變化,但ThreadLocal類型的變量本身的確是一個,這才是本質(zhì)!
(7)ThreadLocal的原理:在ThreadLocal類中有一個Map,用于存儲每一個線程的變量的副本。比如下面的示例實現(xiàn):
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>();
/*
* 默認的構造函數(shù)
*/
private HibernateUtil() {
}
/*
* 靜態(tài)的代碼塊
*/
static {
sessionFactory = new Configuration().configure().buildSessionFactory();
}
/*
* 獲取全新的的session
*/
public static Session openSession() {
return sessionFactory.openSession();
}
/*
* 獲取和線程關聯(lián)的session
*/
public static Session getCurrentSession() {
Session session = threadLocal.get();
// 判斷是是是否得到
if (session == null) {
session = sessionFactory.openSession();
// 把session放到 threadLocal,相當于該session已經(jīng)于線程綁定
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>
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內(nèi)容請查看下面相關鏈接
相關文章
java 使用ConcurrentHashMap和計數(shù)器實現(xiàn)鎖
這篇文章主要介紹了java 使用ConcurrentHashMap和計數(shù)器實現(xiàn)鎖的相關資料,需要的朋友可以參考下2017-05-05
Java List的sort()方法改寫compare()實現(xiàn)升序,降序,倒序的案例
這篇文章主要介紹了Java List的sort()方法改寫compare()實現(xiàn)升序,降序,倒序的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
細數(shù)java中Long與Integer比較容易犯的錯誤總結
下面小編就為大家?guī)硪黄殧?shù)java中Long與Integer比較容易犯的錯誤總結。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01

