ThreadLocal管理Session

利用ThreadLocal模式管理Session


为什么要用ThreadLocal模式呢?

在利用Hibernate开发DAO模块时,我们和Session打的交道最多,

所以如何合理的管理Session,避免Session的频繁创建和销毁,对于提高系统的性能来说是非常重要的;

以往是通过eclipse的插件来自动完成这些代码的,当然效果是不错的。但代码过于冗长,维护困难。

  Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例;

那么Session是否是线程安全的呢? 不安全的。

Session中包含了数据库操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD

就很有可能导致数据存取的混乱,你能够想像那些你根本不能预测执行顺序的线程对你的一条记录进行操作的情形吗?


在Session的众多管理方案中,我们今天来认识一种名ThreadLocal模式(在java1.2推出时支持的)的解决方案。

什么是ThreadLocal模式呢?

它是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。

线程局部变量(ThreadLocal)作用
为每一个使用某变量的线程都提供一个该变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突
从线程的角度看,就好像每一个线程都完全拥有一个该变量

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?
实现的思路:
在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本
ThreadLocal:底层是一个map
{key是当前Thread线程
value:是openSession()生成的Session}


比如下面的示例实现(为了简单,没有考虑集合的泛型):
public class ThreadLocal {
   private Map values = Collections.synchronizedMap(new HashMap());
   public Object get() {
   Thread currentThread = Thread.currentThread(); 
   Object result = values.get(currentThread); 
    if(result == null&&!values.containsKey(currentThread)) {
     result = initialValue();
     values.put(currentThread, result); 
      }
      return result; 
     }
   public void set(Object newValue) {
    values.put(Thread.currentThread(), newValue);
    }
   public Object initialValue() {
    return null; 
   }
  }


具体如何利用ThreadLocal来管理Session?

public class HibernateUtil {
 public static final SessionFactory sessionFactory;
  static {
   try {
    sessionFactory = new Configuration().configure().buildSessionFactory();
    } catch (Throwable ex) {
     throw new ExceptionInInitializerError(ex);
      }
     }
  public static final ThreadLocal<Session>session=new ThreadLocal<Session>();
  public static Session currentSession() throws HibernateException {
    Session s = session.get();
    if(s == null) {
     s = sessionFactory.openSession();
     session.set(s);
     }
     return s;
     }
  public static void closeSession() throws HibernateException {
     Session s = session.get();
    if(s != null) {
      s.close();
     }
     session.set(null);
    }
   }

借助上面的工具类获取Session实例,就可以实现线程范围内的Session共享,从而避免了线程中频繁的创建和销毁Session实例。

在用完后关闭Session对象。

也许大多数时候我们的DAO并不会涉及到多线程的情形,不会将DAO的代码写在Servlet之中,那样不是良好的 设计

通常会在service层的代码里访问DAO的方法。

但是我还是建议采用以上的工具类来管理Session。


当前线程的获取:Thread.currentThread();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值