`
specialbrian
  • 浏览: 60906 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

分享到:
评论

相关推荐

    Hibernager_Session_Manager_ThreadLocal

    描述虽然为空,但我们可以根据标题推测这篇博客可能讨论了如何在多线程环境下利用ThreadLocal来管理Hibernate的Session。在多线程应用中,每个请求通常对应一个独立的线程,而Session是数据库连接的一个会话,如果在...

    java 简单的ThreadLocal示例

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。...通过查看这些示例,你可以更深入地理解ThreadLocal的工作方式以及如何在你的代码中有效地利用它。

    课程hibernate的事务和并发.pdf

    总结来说,理解Hibernate的事务和并发控制,关键在于掌握Session和事务的范围,选择合适的操作单元模式,以及利用拦截器有效地管理Session和事务生命周期。通过这些技术,开发者可以构建出更高效、更可靠的数据库...

    hibernate的事务和并发资料.pdf

    为了实现这一模式,推荐使用拦截器(如ServletFilter)结合ThreadLocal来管理Session和事务,这样可以在处理请求的线程中方便地访问和管理Session。 此外,Hibernate还提供了辅助API来支持行级悲观锁定,利用`...

    hibernate的事务核并发

    在多线程环境中,如Web应用或EJB容器,为了保证`Session`的线程安全和资源的有效利用,可以使用`ThreadLocal`变量来存储当前线程的`Session`实例。然而,在CMT环境中,由于单个session bean可能会被多个线程并行调用...

    hibernate

    在Hibernate3中,推荐使用ThreadLocal模式来管理Session,这可以确保每个线程都有自己的Session实例,避免了并发问题。此外,SessionFactory.getCurrentSession()方法提供了一种便捷的方式来获取当前线程的Session...

    普通类传入对象request

    本文将详细探讨如何在普通类中传入并使用`HttpServletRequest`(简称request)对象,以及通过示例展示如何通过过滤器(Filter)模式实现在业务逻辑类中访问session中的数据。 #### 重要概念解析 - **`...

    Java面试题汇总

    - **Struts2传值机制**:依赖于Action类中的属性,通过页面表单提交数据到Action的属性中,利用OGNL表达式实现数据绑定。 - **特点**: - 动态模型驱动:支持动态数据绑定,简化开发过程。 - 拦截器:用于拦截请求...

    详细解释Spring与Hibernate的整合原理

    通过这种方式,我们可以完全利用 Spring 的 IoC 容器来管理 Hibernate 的配置和数据源,从而实现更高效、更简洁的开发模式。同时,Spring 还提供了强大的事务管理功能,可以通过简单的 XML 或注解配置实现对 ...

    J2EE开发全程实录(JAVA项目开发)

    这部分讲述了多账套的实现,线程变量管理(使用ThreadLocal),事务管理,如事务的边界、隔离级别和Spring的声明型事务。还讨论了会话服务的生命周期管理以及IValueObject接口,为数据访问提供基础支持。 【层间...

    Struts+hibarnate源码

    2. **Session管理**:在Action中,应使用ThreadLocal或Spring的AOP来管理Session的生命周期,避免并发问题。 3. **事务控制**:通过编程式或声明式事务管理确保数据的一致性,一般在Service层处理。 4. **结果集...

    Java个人简历模板12.doc

    在Web OA项目中,开发者使用Struts+Hibernate+Spring构建多层架构,利用ThreadLocal实现分页,运用JBPM和Freemarker实现工作流程,而CRM项目则展示了其在营销管理、销售管理等方面的应用。 综上所述,这位Java...

    我的一个小例子

    例如,UserManager类可能会使用HashMap或ArrayList来存储用户数据,使用PreparedStatement来防止SQL注入,以及使用ThreadLocal来管理数据库连接。 在实际项目中,用户管理系统可能还会涉及到其他技术,如JDBC(Java...

    java面试宝典2019

    GC的目的是提高内存利用率和程序运行效率。 2. **final、finally和finalize**:final用于声明不可改变的变量;finally确保代码块中的语句总会被执行,常用于异常处理;finalize是对象被垃圾回收前调用的方法,一般...

    圣思园 Java web 课件7

    - **使用ThreadLocal**:利用`ThreadLocal`类来实现线程隔离,每个线程拥有独立的变量副本,互不影响。 - **同步控制**:在确实需要共享资源的情况下,可以采用同步代码块或`synchronized`关键字等方式进行同步...

    Java面试题全集(下)

    Session不建议在线程间共享,可以通过ThreadLocal与当前线程绑定来避免创建过多的session。 4. Hibernate的Session方法:Hibernate中的Session提供了多种方法来处理数据库操作,包括load()和get()方法。load()方法...

    多租户代码 根据域名切换

    此外,还可以利用Shiro的Session管理功能,对不同租户的会话进行隔离,确保租户之间的安全性。 至于Vue.js,前端可以根据域名切换不同的主题或配置,以提供个性化的用户体验。可以创建多个Vue组件库,每个库对应一...

    java自定义动态链接数据库示例

    它利用了Hibernate的`SessionFactory`和`Session`机制,保证了多线程环境下的正确性,并且可以通过配置文件轻松地改变数据库连接设置。对于任何需要频繁进行数据库操作的Java应用,这样的设计模式都是十分实用的。

    编写线程安全的JSP程序

    - **设计模式**:利用诸如单例模式、工厂模式等设计模式来限制资源的访问。 总之,编写线程安全的JSP程序需要开发者对线程同步有深入理解,并能够适当地使用各种机制来避免并发问题。通过遵循最佳实践和使用合适的...

Global site tag (gtag.js) - Google Analytics