zoukankan      html  css  js  c++  java
  • ThreadLocal与Synchronized

    package com.demo;
    
    
    
    import org.hibernate.HibernateException;
    import org.hibernate.classic.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    
    public final class HibernateUtil {
        private static SessionFactory sessionFactory;//现实中需要考虑属性的线程安全问题
        /*
        创建线程局部变量threadLocal,用来保存Hibernate的Session
        ThreadLocal在其中设置任何对象,该对象对特定的线程访问将是“全局”且“局部”
        全局:意味着这个线程的任何地方都可以访问到
        局部:每个线程拥有它自己的ThreadLocal变量,一个线程不能访问或修改其他线程的ThreadLocal变量
         */
        private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
        //使用静态代码块 初始化Hibernate
        static{
            try{
                Configuration cfg = new Configuration().configure();
                sessionFactory = cfg.buildSessionFactory();
            }catch (HibernateException ex) {  
               // throw new RuntimeException("Exception building SessionFactory: "  
                 //       + ex.getMessage(), ex);  
            }  
        }
        //获得ThreadLocal对象管理的session实例
        /*
         * 单一实例:在系统中全局使用一个唯一的SessionFactory实例,主要原因是Factory只需要一个实例可以调用方法就可以
         * 另一个方面取得SessionFactory需要的时间太久,每次都实例化,会过分得浪费系统CPU资源
         * 每个线程和使用自身对应的数据库连接session:这里是为每个线程建立一个局部的变量来达到这个目的
         */
        public synchronized static Session getSession(){//同步锁  排队等候访问
            /*
            里面执行先取得当前线程的ThreadLocalMap 然后将threadSession作为key将对应的值取出
             */
            Session s = (Session)threadLocal.get();//s--线程 私有
            if(s==null){// 判断当前线程有无放进去session
                s = sessionFactory.openSession();//创建一个session
                //将新打开的session实例保存到线程局部变量threadLocal中
                threadLocal.set(s);//实际上放到当前线程的ThreadLocal中
            }
            return s;
        }
        //关闭session实例
        //@throws HibernateException
        public static void closeSession() throws HibernateException{
            //从线程局部变量threadLocal中获取之前存入的Session实例
            Session session = threadLocal.get();
            threadLocal.set(null);
            if(session!=null){
                session.close();
            }
        }
        //获得sessionFactory的实例
        public static SessionFactory getSessionFactory(){
            if(sessionFactory == null){
                Configuration cfg = new Configuration().configure();
                sessionFactory = cfg.buildSessionFactory();
            }
            return sessionFactory;
        }
        //关闭sessionFactory
        public static void closeSessionFactory(){
            if(!sessionFactory.isClosed()){    //避免潜在的多线程并发问题
                sessionFactory.close();
            }
        }
    }
    /*
    threadLocal.set(session);将新创建的对象的引用保存到各线程的一个map中,每个线程都有这样的一个map
    执行threadLocal.get()时,各线程从自己的map中取出放进去的对象 取出的是各自的对象
    顺便说一下: synchronized(时间换空间 同步-仅仅提供一份变量 让不同的线程去排队访问)
                ThreadLocal(空间换时间  并发性-为每一个线程都提供一份变量 因为可以同时访问而互不影响)
     * new Configuration.configure() 会在默认的路径下找hiberate.cfg.xml配置文件,请看源代码: 
    
    Java代码  收藏代码
    public Configuration configure() throws HibernateException {  
        configure( "/hibernate.cfg.xml" );  
        return this;  
    }
    
    所以你应该是: 
    Java代码  收藏代码
    Configuration.configure("/hiberate.cfg.xml")
    
    *Configuration是hibernate的入口,在新建一个Configuration的实例的时候,
    *使用不带参数的configure ()方法,hibernate会在classpath里面查找配置文件;
    *Configuration的configure ()方法还支持带参数的访问方式,你可以指定hbm.xml文件的位置,
    *而不是使用默认的classpath下面的配置文件。应该指定配置文件的位置。/
    **/
    package com.demo;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    public class HibernateUtils {
    
        // SessionFactory全局只需要有一个就可以了
        private static SessionFactory sessionFactory;
    
        static {
            Configuration cfg = new Configuration();
            // cfg.configure(); // 读取默认的配置文件(hibernate.cfg.xml)
            // // cfg.configure("hibernate.cfg.xml"); // 读取指定位置的配置文件
            // sessionFactory = cfg.buildSessionFactory();
    
            // cfg.addResource("cn/itcast/a_helloworld/User.hbm.xml");
            // cfg.addClass(User.class); // 去User类所在的包中查找名称为User,后缀为.hbm.xml的文件
    
            // 初始化SessionFactory
            sessionFactory = new Configuration()//
                    .configure()//
                    .buildSessionFactory();
            
        }
    
        /**
         * 获取全局唯一的SessionFactory
         * 
         * @return
         */
        public static SessionFactory getSessionFactory() {
            return sessionFactory;
        }
    
        /**
         * 从全局唯一的SessionFactory中打开一个Session
         * 
         * @return
         */
        public static Session openSession() {
            return sessionFactory.openSession();
        }
    }
  • 相关阅读:
    关于ssh的一篇很好的文章
    课后作业--2 阅读计划及问题
    课后作业--1
    课后作业PPT 7
    大道至简 7、8、读后感
    第六章 读后感
    第五篇 读后感
    数组课后作业
    课后作业1:字串加密
    第四篇 读后感
  • 原文地址:https://www.cnblogs.com/hoobey/p/7470740.html
Copyright © 2011-2022 走看看