您当前的位置: 首页 > 网站编程 > JSP教程 > 技巧:利于ThreadLocal模式管理Session

技巧:利于ThreadLocal模式管理Session

作者:guanchaofeng 来源:不详 发布时间: 2009-03-23 14:56 点击:
在利用Hibernate开发DAO模块时,我们和Session打的交道最多,所以如何合理的管理Session,避免Session的频繁创建和销毁,对于提高系统的性能来说是非常重要的,以往是通过eclipse的插件来自动完成这些代码的,当然效果是不错的,但是总是觉得不爽(没有读懂那

技巧:利于ThreadLocal模式管理Session

在利用Hibernate开发DAO模块时,我们和Session打的交道最多,所以如何合理的管理Session,避免Session的频繁创建和销毁,对于提高系统的性能来说是非常重要的,以往是通过eclipse的插件来自动完成这些代码的,当然效果是不错的,但是总是觉得不爽(没有读懂那些冗长的代码),所以现在打算自己实现Session管理的代码。

我们知道Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例,那么Session是否是线程安全的呢?很遗憾,答案是否定的。Session中包含了数据库操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD,就很有可能导致数据存取的混乱,你能够想像那些你根本不能预测执行顺序的线程对你的一条记录进行操作的情形吗?

在Session的众多管理方案中,我们今天来认识一种名ThreadLocal模式的解决方案。

早在Java1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择。ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用某变量的线程都提供一个该变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有一个该变量。

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。比如下面的示例实现(为了简单,没有考虑集合的泛型):

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呢?Hibernate官方文档手册的示例之中,提供了一个通过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,毕竟我们不能仅仅考虑今天为自己做什么,还应该考虑明天为自己做什么!

分享到:
本文"技巧:利于ThreadLocal模式管理Session"由远航站长收集整理而来,仅供大家学习与参考使用。更多网站制作教程尽在远航站长站。
顶一下
(0)
0%
踩一下
(0)
0%
[点击 次] [返回上一页] [打印]
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
关于本站 - 联系我们 - 网站声明 - 友情连接- 网站地图 - 站点地图 - 返回顶部
Copyright © 2007-2013 www.yhzhan.com(远航站长). All Rights Reserved .
远航站长:为中小站长提供最佳的学习与交流平台,提供网页制作与网站编程等各类网站制作教程.
官方QQ:445490277 网站群:26680406 网站备案号:豫ICP备07500620号-4