JAVA学习网首页 把生活查询网加入收藏 把JAVA学习网设为首页 联系方式
    Hi,JAVA学习
JAVA基础 设计模式 数据库 JavaBeans J2EE JavaDelphi 用户界面 综合文章  
利于ThreadLocal模式管理Session
时间:29/09/2007
作者:未知
来源:网络
小提示点这里把文章加入您的收藏夹,方便下次查看
设置文章字体大小:[ ]

     在利用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,毕竟我们不能仅仅考虑今天为自己做什么,还应该考虑明天为自己做什么!

上一篇:Java设计模式之Bridge

下一篇:如何把一图画变成图形界面的背景

  • 利用JSP获取网页源文件并抓取其中的链接地址
  • 关于Tomcat的并发处理能力
  • Java与C的不同点
  • 我的J2ME网址收藏夹
  • STRUTS中光标定位问题
  • 用J2ME与ASP建立数据库连接
  • windy's j2ee1.4 tutorial (chinese) --overview(002)
  • 使用SWT开发基于Java的图形化用户界面
  • 沉重的翅膀——软件开发,业务?技术?
  • log4j的辅助代码,支持合并多个log4j配置文件。
  • 我理解的IoC和AOP
  • 宠物店大战 (J2EE 与 .NET)
  • 从一个ConnectionPool的实现看Design Pattern的运用 (二)
  • 教你在Jave中实现3d编程简介
  • Spring下业务层的UnitTest--4.15更新
  • 异常设计
  • Hibernate获得成功的十大理由
  • 使用EclipseME开发J2ME程序
  • 返回】 【顶部】 【关闭
    Copyright © 2005-2010 www.594k.com All Rights Reserved.
    版权所有:JAVA学习网 备案序号:皖ICP备06004238号